2014-02-10 02:10:30 +01:00
/*************************************************************************/
/* tree.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
2017-08-27 14:16:55 +02:00
/* https://godotengine.org */
2014-02-10 02:10:30 +01:00
/*************************************************************************/
2022-01-03 21:27:34 +01:00
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
2014-02-10 02:10:30 +01:00
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
2018-01-05 00:50:27 +01:00
2014-02-10 02:10:30 +01:00
# include "tree.h"
2017-08-27 21:07:15 +02:00
2020-11-07 23:33:38 +01:00
# include "core/config/project_settings.h"
2020-04-28 15:19:37 +02:00
# include "core/input/input.h"
2018-09-11 18:13:45 +02:00
# include "core/math/math_funcs.h"
# include "core/os/keyboard.h"
# include "core/os/os.h"
2020-11-07 23:33:38 +01:00
# include "core/string/print_string.h"
2020-09-03 13:22:16 +02:00
# include "core/string/translation.h"
2020-03-04 02:51:12 +01:00
# include "scene/main/window.h"
2014-02-10 02:10:30 +01:00
2020-03-20 03:32:09 +01:00
# include "box_container.h"
2019-04-05 14:06:16 +02:00
# include <limits.h>
2014-02-10 02:10:30 +01:00
Size2 TreeItem : : Cell : : get_icon_size ( ) const {
2020-05-14 16:41:43 +02:00
if ( icon . is_null ( ) ) {
2014-02-10 02:10:30 +01:00
return Size2 ( ) ;
2020-05-14 16:41:43 +02:00
}
if ( icon_region = = Rect2i ( ) ) {
2014-02-10 02:10:30 +01:00
return icon - > get_size ( ) ;
2020-05-14 16:41:43 +02:00
} else {
2014-02-10 02:10:30 +01:00
return icon_region . size ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
}
2015-08-29 06:43:21 +02:00
2017-07-19 22:00:46 +02:00
void TreeItem : : Cell : : draw_icon ( const RID & p_where , const Point2 & p_pos , const Size2 & p_size , const Color & p_color ) const {
2020-05-14 16:41:43 +02:00
if ( icon . is_null ( ) ) {
2014-02-10 02:10:30 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
Size2i dsize = ( p_size = = Size2 ( ) ) ? icon - > get_size ( ) : p_size ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
if ( icon_region = = Rect2i ( ) ) {
2017-07-19 22:00:46 +02:00
icon - > draw_rect_region ( p_where , Rect2 ( p_pos , dsize ) , Rect2 ( Point2 ( ) , icon - > get_size ( ) ) , p_color ) ;
2014-02-10 02:10:30 +01:00
} else {
2017-07-19 22:00:46 +02:00
icon - > draw_rect_region ( p_where , Rect2 ( p_pos , dsize ) , icon_region , p_color ) ;
2014-02-10 02:10:30 +01:00
}
}
void TreeItem : : _changed_notify ( int p_cell ) {
2017-03-05 16:44:50 +01:00
tree - > item_changed ( p_cell , this ) ;
2014-02-10 02:10:30 +01:00
}
void TreeItem : : _changed_notify ( ) {
2017-03-05 16:44:50 +01:00
tree - > item_changed ( - 1 , this ) ;
2014-02-10 02:10:30 +01:00
}
void TreeItem : : _cell_selected ( int p_cell ) {
2017-03-05 16:44:50 +01:00
tree - > item_selected ( p_cell , this ) ;
2014-02-10 02:10:30 +01:00
}
void TreeItem : : _cell_deselected ( int p_cell ) {
2017-03-05 16:44:50 +01:00
tree - > item_deselected ( p_cell , this ) ;
2014-02-10 02:10:30 +01:00
}
2021-03-07 21:07:30 +01:00
void TreeItem : : _change_tree ( Tree * p_tree ) {
if ( p_tree = = tree ) {
return ;
}
TreeItem * c = first_child ;
while ( c ) {
c - > _change_tree ( p_tree ) ;
c = c - > next ;
}
2021-07-03 22:36:22 +02:00
if ( tree ) {
if ( tree - > root = = this ) {
tree - > root = nullptr ;
}
2021-03-07 21:07:30 +01:00
2021-07-03 22:36:22 +02:00
if ( tree - > popup_edited_item = = this ) {
tree - > popup_edited_item = nullptr ;
tree - > pressing_for_editor = false ;
}
2021-03-07 21:07:30 +01:00
2021-07-03 22:36:22 +02:00
if ( tree - > cache . hover_item = = this ) {
tree - > cache . hover_item = nullptr ;
}
2021-03-07 21:07:30 +01:00
2021-07-03 22:36:22 +02:00
if ( tree - > selected_item = = this ) {
tree - > selected_item = nullptr ;
}
2021-03-07 21:07:30 +01:00
2021-07-03 22:36:22 +02:00
if ( tree - > drop_mode_over = = this ) {
tree - > drop_mode_over = nullptr ;
}
2021-03-07 21:07:30 +01:00
2021-07-03 22:36:22 +02:00
if ( tree - > single_select_defer = = this ) {
tree - > single_select_defer = nullptr ;
}
if ( tree - > edited_item = = this ) {
tree - > edited_item = nullptr ;
tree - > pressing_for_editor = false ;
}
2021-03-07 21:07:30 +01:00
2021-07-03 22:36:22 +02:00
tree - > update ( ) ;
2021-03-07 21:07:30 +01:00
}
tree = p_tree ;
if ( tree ) {
2021-07-03 22:36:22 +02:00
tree - > update ( ) ;
2021-03-07 21:07:30 +01:00
cells . resize ( tree - > columns . size ( ) ) ;
}
}
2014-02-10 02:10:30 +01:00
/* cell mode */
2017-03-05 16:44:50 +01:00
void TreeItem : : set_cell_mode ( int p_column , TreeCellMode p_mode ) {
ERR_FAIL_INDEX ( p_column , cells . size ( ) ) ;
2021-09-24 10:11:44 +02:00
2018-07-25 03:11:03 +02:00
Cell & c = cells . write [ p_column ] ;
2017-03-05 16:44:50 +01:00
c . mode = p_mode ;
c . min = 0 ;
c . max = 100 ;
c . step = 1 ;
c . val = 0 ;
c . checked = false ;
2019-06-11 20:43:37 +02:00
c . icon = Ref < Texture2D > ( ) ;
2017-03-05 16:44:50 +01:00
c . text = " " ;
2020-09-03 13:22:16 +02:00
c . dirty = true ;
2017-03-05 16:44:50 +01:00
c . icon_max_w = 0 ;
2021-09-24 10:11:44 +02:00
c . cached_minimum_size_dirty = true ;
2014-02-10 02:10:30 +01:00
_changed_notify ( p_column ) ;
}
2017-03-05 16:44:50 +01:00
TreeItem : : TreeCellMode TreeItem : : get_cell_mode ( int p_column ) const {
ERR_FAIL_INDEX_V ( p_column , cells . size ( ) , TreeItem : : CELL_MODE_STRING ) ;
2014-02-10 02:10:30 +01:00
return cells [ p_column ] . mode ;
}
/* check mode */
2017-03-05 16:44:50 +01:00
void TreeItem : : set_checked ( int p_column , bool p_checked ) {
ERR_FAIL_INDEX ( p_column , cells . size ( ) ) ;
2021-09-24 10:11:44 +02:00
2018-07-25 03:11:03 +02:00
cells . write [ p_column ] . checked = p_checked ;
2021-07-22 22:34:54 +02:00
cells . write [ p_column ] . indeterminate = false ;
2021-09-24 10:11:44 +02:00
cells . write [ p_column ] . cached_minimum_size_dirty = true ;
2021-07-22 22:34:54 +02:00
_changed_notify ( p_column ) ;
}
void TreeItem : : set_indeterminate ( int p_column , bool p_indeterminate ) {
ERR_FAIL_INDEX ( p_column , cells . size ( ) ) ;
2021-09-24 10:11:44 +02:00
2021-07-22 22:34:54 +02:00
// Prevent uncheck if indeterminate set to false twice
if ( p_indeterminate = = cells [ p_column ] . indeterminate ) {
return ;
}
2021-09-24 10:11:44 +02:00
2021-07-22 22:34:54 +02:00
cells . write [ p_column ] . indeterminate = p_indeterminate ;
cells . write [ p_column ] . checked = false ;
2021-09-24 10:11:44 +02:00
cells . write [ p_column ] . cached_minimum_size_dirty = true ;
2014-02-10 02:10:30 +01:00
_changed_notify ( p_column ) ;
}
bool TreeItem : : is_checked ( int p_column ) const {
2017-03-05 16:44:50 +01:00
ERR_FAIL_INDEX_V ( p_column , cells . size ( ) , false ) ;
2014-02-10 02:10:30 +01:00
return cells [ p_column ] . checked ;
}
2021-07-22 22:34:54 +02:00
bool TreeItem : : is_indeterminate ( int p_column ) const {
ERR_FAIL_INDEX_V ( p_column , cells . size ( ) , false ) ;
return cells [ p_column ] . indeterminate ;
}
2021-09-17 17:50:24 +02:00
void TreeItem : : propagate_check ( int p_column , bool p_emit_signal ) {
bool ch = cells [ p_column ] . checked ;
if ( p_emit_signal ) {
tree - > emit_signal ( " check_propagated_to_item " , this , p_column ) ;
}
_propagate_check_through_children ( p_column , ch , p_emit_signal ) ;
_propagate_check_through_parents ( p_column , p_emit_signal ) ;
}
void TreeItem : : _propagate_check_through_children ( int p_column , bool p_checked , bool p_emit_signal ) {
TreeItem * current = get_first_child ( ) ;
while ( current ) {
current - > set_checked ( p_column , p_checked ) ;
if ( p_emit_signal ) {
current - > tree - > emit_signal ( " check_propagated_to_item " , current , p_column ) ;
}
current - > _propagate_check_through_children ( p_column , p_checked , p_emit_signal ) ;
current = current - > get_next ( ) ;
}
}
void TreeItem : : _propagate_check_through_parents ( int p_column , bool p_emit_signal ) {
TreeItem * current = get_parent ( ) ;
if ( ! current ) {
return ;
}
bool all_unchecked_and_not_indeterminate = true ;
bool any_unchecked_or_indeterminate = false ;
TreeItem * child_item = current - > get_first_child ( ) ;
while ( child_item ) {
if ( ! child_item - > is_checked ( p_column ) ) {
any_unchecked_or_indeterminate = true ;
if ( child_item - > is_indeterminate ( p_column ) ) {
all_unchecked_and_not_indeterminate = false ;
break ;
}
} else {
all_unchecked_and_not_indeterminate = false ;
}
child_item = child_item - > get_next ( ) ;
}
if ( all_unchecked_and_not_indeterminate ) {
current - > set_checked ( p_column , false ) ;
} else if ( any_unchecked_or_indeterminate ) {
current - > set_indeterminate ( p_column , true ) ;
} else {
current - > set_checked ( p_column , true ) ;
}
if ( p_emit_signal ) {
current - > tree - > emit_signal ( " check_propagated_to_item " , current , p_column ) ;
}
current - > _propagate_check_through_parents ( p_column , p_emit_signal ) ;
}
2017-03-05 16:44:50 +01:00
void TreeItem : : set_text ( int p_column , String p_text ) {
ERR_FAIL_INDEX ( p_column , cells . size ( ) ) ;
2018-07-25 03:11:03 +02:00
cells . write [ p_column ] . text = p_text ;
2020-09-03 13:22:16 +02:00
cells . write [ p_column ] . dirty = true ;
2014-02-10 02:10:30 +01:00
2018-09-22 22:31:56 +02:00
if ( cells [ p_column ] . mode = = TreeItem : : CELL_MODE_RANGE ) {
2017-11-15 19:50:37 +01:00
Vector < String > strings = p_text . split ( " , " ) ;
2018-07-25 03:11:03 +02:00
cells . write [ p_column ] . min = INT_MAX ;
cells . write [ p_column ] . max = INT_MIN ;
2017-11-15 19:50:37 +01:00
for ( int i = 0 ; i < strings . size ( ) ; i + + ) {
int value = i ;
2020-12-15 13:04:21 +01:00
if ( ! strings [ i ] . get_slicec ( ' : ' , 1 ) . is_empty ( ) ) {
2017-11-15 19:50:37 +01:00
value = strings [ i ] . get_slicec ( ' : ' , 1 ) . to_int ( ) ;
}
2018-07-25 03:11:03 +02:00
cells . write [ p_column ] . min = MIN ( cells [ p_column ] . min , value ) ;
cells . write [ p_column ] . max = MAX ( cells [ p_column ] . max , value ) ;
2017-11-15 19:50:37 +01:00
}
2018-07-25 03:11:03 +02:00
cells . write [ p_column ] . step = 0 ;
2014-02-10 02:10:30 +01:00
}
2021-09-24 10:11:44 +02:00
cells . write [ p_column ] . cached_minimum_size_dirty = true ;
2014-02-10 02:10:30 +01:00
_changed_notify ( p_column ) ;
}
String TreeItem : : get_text ( int p_column ) const {
2017-03-05 16:44:50 +01:00
ERR_FAIL_INDEX_V ( p_column , cells . size ( ) , " " ) ;
2014-02-10 02:10:30 +01:00
return cells [ p_column ] . text ;
}
2020-09-03 13:22:16 +02:00
void TreeItem : : set_text_direction ( int p_column , Control : : TextDirection p_text_direction ) {
ERR_FAIL_INDEX ( p_column , cells . size ( ) ) ;
ERR_FAIL_COND ( ( int ) p_text_direction < - 1 | | ( int ) p_text_direction > 3 ) ;
if ( cells [ p_column ] . text_direction ! = p_text_direction ) {
cells . write [ p_column ] . text_direction = p_text_direction ;
cells . write [ p_column ] . dirty = true ;
_changed_notify ( p_column ) ;
}
2021-09-24 10:11:44 +02:00
cells . write [ p_column ] . cached_minimum_size_dirty = true ;
2020-09-03 13:22:16 +02:00
}
Control : : TextDirection TreeItem : : get_text_direction ( int p_column ) const {
ERR_FAIL_INDEX_V ( p_column , cells . size ( ) , Control : : TEXT_DIRECTION_INHERITED ) ;
return cells [ p_column ] . text_direction ;
}
void TreeItem : : clear_opentype_features ( int p_column ) {
ERR_FAIL_INDEX ( p_column , cells . size ( ) ) ;
2021-09-24 10:11:44 +02:00
2020-09-03 13:22:16 +02:00
cells . write [ p_column ] . opentype_features . clear ( ) ;
cells . write [ p_column ] . dirty = true ;
2021-09-24 10:11:44 +02:00
cells . write [ p_column ] . cached_minimum_size_dirty = true ;
2020-09-03 13:22:16 +02:00
_changed_notify ( p_column ) ;
}
void TreeItem : : set_opentype_feature ( int p_column , const String & p_name , int p_value ) {
ERR_FAIL_INDEX ( p_column , cells . size ( ) ) ;
int32_t tag = TS - > name_to_tag ( p_name ) ;
if ( ! cells [ p_column ] . opentype_features . has ( tag ) | | ( int ) cells [ p_column ] . opentype_features [ tag ] ! = p_value ) {
cells . write [ p_column ] . opentype_features [ tag ] = p_value ;
cells . write [ p_column ] . dirty = true ;
2021-09-24 10:11:44 +02:00
cells . write [ p_column ] . cached_minimum_size_dirty = true ;
2020-09-03 13:22:16 +02:00
_changed_notify ( p_column ) ;
}
}
int TreeItem : : get_opentype_feature ( int p_column , const String & p_name ) const {
ERR_FAIL_INDEX_V ( p_column , cells . size ( ) , - 1 ) ;
int32_t tag = TS - > name_to_tag ( p_name ) ;
if ( ! cells [ p_column ] . opentype_features . has ( tag ) ) {
return - 1 ;
}
return cells [ p_column ] . opentype_features [ tag ] ;
}
void TreeItem : : set_structured_text_bidi_override ( int p_column , Control : : StructuredTextParser p_parser ) {
ERR_FAIL_INDEX ( p_column , cells . size ( ) ) ;
2021-09-24 10:11:44 +02:00
2020-09-03 13:22:16 +02:00
if ( cells [ p_column ] . st_parser ! = p_parser ) {
cells . write [ p_column ] . st_parser = p_parser ;
cells . write [ p_column ] . dirty = true ;
2021-09-24 10:11:44 +02:00
cells . write [ p_column ] . cached_minimum_size_dirty = true ;
2020-09-03 13:22:16 +02:00
_changed_notify ( p_column ) ;
}
}
Control : : StructuredTextParser TreeItem : : get_structured_text_bidi_override ( int p_column ) const {
ERR_FAIL_INDEX_V ( p_column , cells . size ( ) , Control : : STRUCTURED_TEXT_NONE ) ;
return cells [ p_column ] . st_parser ;
}
void TreeItem : : set_structured_text_bidi_override_options ( int p_column , Array p_args ) {
ERR_FAIL_INDEX ( p_column , cells . size ( ) ) ;
2021-09-24 10:11:44 +02:00
2020-09-03 13:22:16 +02:00
cells . write [ p_column ] . st_args = p_args ;
cells . write [ p_column ] . dirty = true ;
2021-09-24 10:11:44 +02:00
cells . write [ p_column ] . cached_minimum_size_dirty = true ;
2020-09-03 13:22:16 +02:00
_changed_notify ( p_column ) ;
}
Array TreeItem : : get_structured_text_bidi_override_options ( int p_column ) const {
ERR_FAIL_INDEX_V ( p_column , cells . size ( ) , Array ( ) ) ;
return cells [ p_column ] . st_args ;
}
void TreeItem : : set_language ( int p_column , const String & p_language ) {
ERR_FAIL_INDEX ( p_column , cells . size ( ) ) ;
2021-09-24 10:11:44 +02:00
2020-09-03 13:22:16 +02:00
if ( cells [ p_column ] . language ! = p_language ) {
cells . write [ p_column ] . language = p_language ;
cells . write [ p_column ] . dirty = true ;
2021-09-24 10:11:44 +02:00
cells . write [ p_column ] . cached_minimum_size_dirty = true ;
2020-09-03 13:22:16 +02:00
_changed_notify ( p_column ) ;
}
}
String TreeItem : : get_language ( int p_column ) const {
ERR_FAIL_INDEX_V ( p_column , cells . size ( ) , " " ) ;
return cells [ p_column ] . language ;
}
2017-03-05 16:44:50 +01:00
void TreeItem : : set_suffix ( int p_column , String p_suffix ) {
ERR_FAIL_INDEX ( p_column , cells . size ( ) ) ;
2021-09-24 10:11:44 +02:00
2018-07-25 03:11:03 +02:00
cells . write [ p_column ] . suffix = p_suffix ;
2021-09-24 10:11:44 +02:00
cells . write [ p_column ] . cached_minimum_size_dirty = true ;
2016-08-31 04:44:14 +02:00
_changed_notify ( p_column ) ;
}
String TreeItem : : get_suffix ( int p_column ) const {
2017-03-05 16:44:50 +01:00
ERR_FAIL_INDEX_V ( p_column , cells . size ( ) , " " ) ;
2016-08-31 04:44:14 +02:00
return cells [ p_column ] . suffix ;
}
2014-02-10 02:10:30 +01:00
2019-06-11 20:43:37 +02:00
void TreeItem : : set_icon ( int p_column , const Ref < Texture2D > & p_icon ) {
2017-03-05 16:44:50 +01:00
ERR_FAIL_INDEX ( p_column , cells . size ( ) ) ;
2021-09-24 10:11:44 +02:00
2018-07-25 03:11:03 +02:00
cells . write [ p_column ] . icon = p_icon ;
2021-09-24 10:11:44 +02:00
cells . write [ p_column ] . cached_minimum_size_dirty = true ;
2014-02-10 02:10:30 +01:00
_changed_notify ( p_column ) ;
}
2019-06-11 20:43:37 +02:00
Ref < Texture2D > TreeItem : : get_icon ( int p_column ) const {
ERR_FAIL_INDEX_V ( p_column , cells . size ( ) , Ref < Texture2D > ( ) ) ;
2014-02-10 02:10:30 +01:00
return cells [ p_column ] . icon ;
}
2017-03-05 16:44:50 +01:00
void TreeItem : : set_icon_region ( int p_column , const Rect2 & p_icon_region ) {
ERR_FAIL_INDEX ( p_column , cells . size ( ) ) ;
2021-09-24 10:11:44 +02:00
2018-07-25 03:11:03 +02:00
cells . write [ p_column ] . icon_region = p_icon_region ;
2021-09-24 10:11:44 +02:00
cells . write [ p_column ] . cached_minimum_size_dirty = true ;
2014-02-10 02:10:30 +01:00
_changed_notify ( p_column ) ;
}
Rect2 TreeItem : : get_icon_region ( int p_column ) const {
2017-03-05 16:44:50 +01:00
ERR_FAIL_INDEX_V ( p_column , cells . size ( ) , Rect2 ( ) ) ;
2014-02-10 02:10:30 +01:00
return cells [ p_column ] . icon_region ;
}
2019-08-24 17:13:48 +02:00
void TreeItem : : set_icon_modulate ( int p_column , const Color & p_modulate ) {
2017-07-19 22:00:46 +02:00
ERR_FAIL_INDEX ( p_column , cells . size ( ) ) ;
2019-08-24 17:13:48 +02:00
cells . write [ p_column ] . icon_color = p_modulate ;
2017-07-19 22:00:46 +02:00
_changed_notify ( p_column ) ;
}
2019-08-24 17:13:48 +02:00
Color TreeItem : : get_icon_modulate ( int p_column ) const {
2017-07-19 22:00:46 +02:00
ERR_FAIL_INDEX_V ( p_column , cells . size ( ) , Color ( ) ) ;
return cells [ p_column ] . icon_color ;
}
2017-03-05 16:44:50 +01:00
void TreeItem : : set_icon_max_width ( int p_column , int p_max ) {
ERR_FAIL_INDEX ( p_column , cells . size ( ) ) ;
2021-09-24 10:11:44 +02:00
2018-07-25 03:11:03 +02:00
cells . write [ p_column ] . icon_max_w = p_max ;
2021-09-24 10:11:44 +02:00
cells . write [ p_column ] . cached_minimum_size_dirty = true ;
2014-02-10 02:10:30 +01:00
_changed_notify ( p_column ) ;
}
int TreeItem : : get_icon_max_width ( int p_column ) const {
2017-03-05 16:44:50 +01:00
ERR_FAIL_INDEX_V ( p_column , cells . size ( ) , 0 ) ;
2014-02-10 02:10:30 +01:00
return cells [ p_column ] . icon_max_w ;
}
/* range works for mode number or mode combo */
2017-03-05 16:44:50 +01:00
void TreeItem : : set_range ( int p_column , double p_value ) {
ERR_FAIL_INDEX ( p_column , cells . size ( ) ) ;
2020-05-14 16:41:43 +02:00
if ( cells [ p_column ] . step > 0 ) {
2020-12-21 19:02:57 +01:00
p_value = Math : : snapped ( p_value , cells [ p_column ] . step ) ;
2020-05-14 16:41:43 +02:00
}
if ( p_value < cells [ p_column ] . min ) {
2017-03-05 16:44:50 +01:00
p_value = cells [ p_column ] . min ;
2020-05-14 16:41:43 +02:00
}
if ( p_value > cells [ p_column ] . max ) {
2017-03-05 16:44:50 +01:00
p_value = cells [ p_column ] . max ;
2020-05-14 16:41:43 +02:00
}
2015-08-31 00:37:23 +02:00
2018-07-25 03:11:03 +02:00
cells . write [ p_column ] . val = p_value ;
2020-09-03 13:22:16 +02:00
cells . write [ p_column ] . dirty = true ;
2014-02-10 02:10:30 +01:00
_changed_notify ( p_column ) ;
}
double TreeItem : : get_range ( int p_column ) const {
2017-03-05 16:44:50 +01:00
ERR_FAIL_INDEX_V ( p_column , cells . size ( ) , 0 ) ;
2014-02-10 02:10:30 +01:00
return cells [ p_column ] . val ;
}
bool TreeItem : : is_range_exponential ( int p_column ) const {
2017-03-05 16:44:50 +01:00
ERR_FAIL_INDEX_V ( p_column , cells . size ( ) , false ) ;
2014-02-10 02:10:30 +01:00
return cells [ p_column ] . expr ;
}
2020-05-14 14:29:06 +02:00
2017-03-05 16:44:50 +01:00
void TreeItem : : set_range_config ( int p_column , double p_min , double p_max , double p_step , bool p_exp ) {
ERR_FAIL_INDEX ( p_column , cells . size ( ) ) ;
2018-07-25 03:11:03 +02:00
cells . write [ p_column ] . min = p_min ;
cells . write [ p_column ] . max = p_max ;
cells . write [ p_column ] . step = p_step ;
cells . write [ p_column ] . expr = p_exp ;
2014-02-10 02:10:30 +01:00
_changed_notify ( p_column ) ;
}
2017-03-05 16:44:50 +01:00
void TreeItem : : get_range_config ( int p_column , double & r_min , double & r_max , double & r_step ) const {
ERR_FAIL_INDEX ( p_column , cells . size ( ) ) ;
r_min = cells [ p_column ] . min ;
r_max = cells [ p_column ] . max ;
r_step = cells [ p_column ] . step ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
void TreeItem : : set_metadata ( int p_column , const Variant & p_meta ) {
ERR_FAIL_INDEX ( p_column , cells . size ( ) ) ;
2018-07-25 03:11:03 +02:00
cells . write [ p_column ] . meta = p_meta ;
2014-02-10 02:10:30 +01:00
}
Variant TreeItem : : get_metadata ( int p_column ) const {
2017-03-05 16:44:50 +01:00
ERR_FAIL_INDEX_V ( p_column , cells . size ( ) , Variant ( ) ) ;
2014-02-10 02:10:30 +01:00
return cells [ p_column ] . meta ;
}
2017-03-05 16:44:50 +01:00
void TreeItem : : set_custom_draw ( int p_column , Object * p_object , const StringName & p_callback ) {
ERR_FAIL_INDEX ( p_column , cells . size ( ) ) ;
2014-02-10 02:10:30 +01:00
ERR_FAIL_NULL ( p_object ) ;
2018-07-25 03:11:03 +02:00
cells . write [ p_column ] . custom_draw_obj = p_object - > get_instance_id ( ) ;
cells . write [ p_column ] . custom_draw_callback = p_callback ;
2014-02-10 02:10:30 +01:00
}
void TreeItem : : set_collapsed ( bool p_collapsed ) {
2020-05-14 16:41:43 +02:00
if ( collapsed = = p_collapsed | | ! tree ) {
2014-02-10 02:10:30 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2017-03-05 16:44:50 +01:00
collapsed = p_collapsed ;
2014-02-10 02:10:30 +01:00
TreeItem * ci = tree - > selected_item ;
if ( ci ) {
2017-03-05 16:44:50 +01:00
while ( ci & & ci ! = this ) {
ci = ci - > parent ;
2014-02-10 02:10:30 +01:00
}
Fix misc. source comment typos
Found using `codespell -q 3 -S ./thirdparty,*.po -L ang,ba,cas,dof,doubleclick,fave,hist,leapyear,lod,nd,numer,ois,paket,seeked,sinc,switchs,te,uint -D ~/Projects/codespell/codespell_lib/data/dictionary.txt `
2019-09-19 20:36:39 +02:00
if ( ci ) { // collapsing cursor/selected, move it!
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
if ( tree - > select_mode = = Tree : : SELECT_MULTI ) {
tree - > selected_item = this ;
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " cell_selected " ) ) ;
2014-02-10 02:10:30 +01:00
} else {
select ( tree - > selected_col ) ;
}
tree - > update ( ) ;
}
}
_changed_notify ( ) ;
2021-07-17 23:22:52 +02:00
tree - > emit_signal ( SNAME ( " item_collapsed " ) , this ) ;
2014-02-10 02:10:30 +01:00
}
bool TreeItem : : is_collapsed ( ) {
return collapsed ;
}
2021-03-19 13:57:52 +01:00
void TreeItem : : uncollapse_tree ( ) {
TreeItem * t = this ;
while ( t ) {
t - > set_collapsed ( false ) ;
t = t - > parent ;
}
}
2017-09-05 14:31:07 +02:00
void TreeItem : : set_custom_minimum_height ( int p_height ) {
custom_min_height = p_height ;
2021-09-24 10:11:44 +02:00
2022-01-27 17:34:33 +01:00
for ( Cell & c : cells ) {
2021-09-24 10:11:44 +02:00
c . cached_minimum_size_dirty = true ;
2022-01-27 17:34:33 +01:00
}
2021-09-24 10:11:44 +02:00
2017-09-05 14:31:07 +02:00
_changed_notify ( ) ;
}
int TreeItem : : get_custom_minimum_height ( ) const {
return custom_min_height ;
}
2021-03-07 21:07:30 +01:00
/* Item manipulation */
TreeItem * TreeItem : : create_child ( int p_idx ) {
TreeItem * ti = memnew ( TreeItem ( tree ) ) ;
if ( tree ) {
ti - > cells . resize ( tree - > columns . size ( ) ) ;
2021-07-03 22:36:22 +02:00
tree - > update ( ) ;
2021-03-07 21:07:30 +01:00
}
TreeItem * l_prev = nullptr ;
TreeItem * c = first_child ;
int idx = 0 ;
while ( c ) {
if ( idx + + = = p_idx ) {
c - > prev = ti ;
ti - > next = c ;
break ;
}
l_prev = c ;
c = c - > next ;
}
if ( l_prev ) {
l_prev - > next = ti ;
ti - > prev = l_prev ;
if ( ! children_cache . is_empty ( ) ) {
if ( ti - > next ) {
children_cache . insert ( p_idx , ti ) ;
} else {
children_cache . append ( ti ) ;
}
}
} else {
first_child = ti ;
if ( ! children_cache . is_empty ( ) ) {
children_cache . insert ( 0 , ti ) ;
}
}
ti - > parent = this ;
return ti ;
}
2021-06-28 15:40:56 +02:00
Tree * TreeItem : : get_tree ( ) const {
2021-03-07 21:07:30 +01:00
return tree ;
}
2021-06-28 15:40:56 +02:00
TreeItem * TreeItem : : get_next ( ) const {
2014-02-10 02:10:30 +01:00
return next ;
}
TreeItem * TreeItem : : get_prev ( ) {
2021-03-07 21:07:30 +01:00
if ( prev ) {
return prev ;
2020-05-14 16:41:43 +02:00
}
2015-08-31 00:37:23 +02:00
2021-03-07 21:07:30 +01:00
if ( ! parent | | parent - > first_child = = this ) {
return nullptr ;
}
// This is an edge case
TreeItem * l_prev = parent - > first_child ;
while ( l_prev & & l_prev - > next ! = this ) {
l_prev = l_prev - > next ;
2020-05-14 16:41:43 +02:00
}
2015-08-31 00:37:23 +02:00
2021-03-07 21:07:30 +01:00
prev = l_prev ;
2014-02-10 02:10:30 +01:00
return prev ;
}
2021-06-28 15:40:56 +02:00
TreeItem * TreeItem : : get_parent ( ) const {
2014-02-10 02:10:30 +01:00
return parent ;
}
2021-06-28 15:40:56 +02:00
TreeItem * TreeItem : : get_first_child ( ) const {
2021-03-07 21:07:30 +01:00
return first_child ;
2014-02-10 02:10:30 +01:00
}
2019-05-11 18:32:53 +02:00
TreeItem * TreeItem : : get_prev_visible ( bool p_wrap ) {
2017-03-05 16:44:50 +01:00
TreeItem * current = this ;
2014-02-10 02:10:30 +01:00
TreeItem * prev = current - > get_prev ( ) ;
if ( ! prev ) {
2017-03-05 16:44:50 +01:00
current = current - > parent ;
2019-05-11 18:32:53 +02:00
if ( current = = tree - > root & & tree - > hide_root ) {
2020-04-02 01:20:12 +02:00
return nullptr ;
2019-05-11 18:32:53 +02:00
} else if ( ! current ) {
if ( p_wrap ) {
current = this ;
TreeItem * temp = this - > get_next_visible ( ) ;
while ( temp ) {
current = temp ;
temp = temp - > get_next_visible ( ) ;
}
} else {
2020-04-02 01:20:12 +02:00
return nullptr ;
2019-05-11 18:32:53 +02:00
}
}
2014-02-10 02:10:30 +01:00
} else {
2017-03-05 16:44:50 +01:00
current = prev ;
2021-03-07 21:07:30 +01:00
while ( ! current - > collapsed & & current - > first_child ) {
2014-02-10 02:10:30 +01:00
//go to the very end
2021-03-07 21:07:30 +01:00
current = current - > first_child ;
2020-05-14 16:41:43 +02:00
while ( current - > next ) {
2017-03-05 16:44:50 +01:00
current = current - > next ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
}
}
return current ;
}
2019-05-11 18:32:53 +02:00
TreeItem * TreeItem : : get_next_visible ( bool p_wrap ) {
2017-03-05 16:44:50 +01:00
TreeItem * current = this ;
2014-02-10 02:10:30 +01:00
2021-03-07 21:07:30 +01:00
if ( ! current - > collapsed & & current - > first_child ) {
current = current - > first_child ;
2014-02-10 02:10:30 +01:00
} else if ( current - > next ) {
2017-03-05 16:44:50 +01:00
current = current - > next ;
2014-02-10 02:10:30 +01:00
} else {
2017-03-05 16:44:50 +01:00
while ( current & & ! current - > next ) {
current = current - > parent ;
2014-02-10 02:10:30 +01:00
}
2019-05-11 18:32:53 +02:00
if ( ! current ) {
2020-05-14 16:41:43 +02:00
if ( p_wrap ) {
2019-05-11 18:32:53 +02:00
return tree - > root ;
2020-05-14 16:41:43 +02:00
} else {
2020-04-02 01:20:12 +02:00
return nullptr ;
2020-05-14 16:41:43 +02:00
}
2019-05-11 18:32:53 +02:00
} else {
2017-03-05 16:44:50 +01:00
current = current - > next ;
2019-05-11 18:32:53 +02:00
}
2014-02-10 02:10:30 +01:00
}
return current ;
}
2021-03-07 21:07:30 +01:00
TreeItem * TreeItem : : get_child ( int p_idx ) {
_create_children_cache ( ) ;
ERR_FAIL_INDEX_V ( p_idx , children_cache . size ( ) , nullptr ) ;
return children_cache . get ( p_idx ) ;
}
int TreeItem : : get_child_count ( ) {
_create_children_cache ( ) ;
return children_cache . size ( ) ;
}
Array TreeItem : : get_children ( ) {
int size = get_child_count ( ) ;
Array arr ;
arr . resize ( size ) ;
for ( int i = 0 ; i < size ; i + + ) {
arr [ i ] = children_cache [ i ] ;
}
return arr ;
}
int TreeItem : : get_index ( ) {
int idx = 0 ;
TreeItem * c = this ;
while ( c ) {
c = c - > get_prev ( ) ;
idx + + ;
}
return idx - 1 ;
}
void TreeItem : : move_before ( TreeItem * p_item ) {
2014-02-10 02:10:30 +01:00
ERR_FAIL_NULL ( p_item ) ;
2021-03-07 21:07:30 +01:00
ERR_FAIL_COND ( is_root ) ;
ERR_FAIL_COND ( ! p_item - > parent ) ;
2014-02-10 02:10:30 +01:00
2021-03-07 21:07:30 +01:00
if ( p_item = = this ) {
return ;
}
2014-02-10 02:10:30 +01:00
2021-03-07 21:07:30 +01:00
TreeItem * p = p_item - > parent ;
while ( p ) {
ERR_FAIL_COND_MSG ( p = = this , " Can't move to a descendant " ) ;
p = p - > parent ;
}
2014-02-10 02:10:30 +01:00
2021-03-07 21:07:30 +01:00
Tree * old_tree = tree ;
_unlink_from_tree ( ) ;
_change_tree ( p_item - > tree ) ;
parent = p_item - > parent ;
TreeItem * item_prev = p_item - > get_prev ( ) ;
if ( item_prev ) {
item_prev - > next = this ;
parent - > children_cache . clear ( ) ;
} else {
parent - > first_child = this ;
parent - > children_cache . insert ( 0 , this ) ;
}
prev = item_prev ;
next = p_item ;
p_item - > prev = this ;
2021-07-03 22:36:22 +02:00
if ( tree & & old_tree = = tree ) {
2021-03-07 21:07:30 +01:00
tree - > update ( ) ;
}
}
void TreeItem : : move_after ( TreeItem * p_item ) {
ERR_FAIL_NULL ( p_item ) ;
ERR_FAIL_COND ( is_root ) ;
ERR_FAIL_COND ( ! p_item - > parent ) ;
if ( p_item = = this ) {
return ;
}
2014-02-10 02:10:30 +01:00
2021-03-07 21:07:30 +01:00
TreeItem * p = p_item - > parent ;
while ( p ) {
ERR_FAIL_COND_MSG ( p = = this , " Can't move to a descendant " ) ;
p = p - > parent ;
2014-02-10 02:10:30 +01:00
}
2021-03-07 21:07:30 +01:00
Tree * old_tree = tree ;
_unlink_from_tree ( ) ;
_change_tree ( p_item - > tree ) ;
if ( p_item - > next ) {
p_item - > next - > prev = this ;
}
parent = p_item - > parent ;
prev = p_item ;
next = p_item - > next ;
p_item - > next = this ;
if ( next ) {
parent - > children_cache . clear ( ) ;
} else {
parent - > children_cache . append ( this ) ;
}
2021-07-03 22:36:22 +02:00
if ( tree & & old_tree = = tree ) {
2021-03-07 21:07:30 +01:00
tree - > update ( ) ;
}
}
void TreeItem : : remove_child ( TreeItem * p_item ) {
ERR_FAIL_NULL ( p_item ) ;
ERR_FAIL_COND ( p_item - > parent ! = this ) ;
p_item - > _unlink_from_tree ( ) ;
p_item - > prev = nullptr ;
p_item - > next = nullptr ;
p_item - > parent = nullptr ;
if ( tree ) {
tree - > update ( ) ;
}
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
void TreeItem : : set_selectable ( int p_column , bool p_selectable ) {
ERR_FAIL_INDEX ( p_column , cells . size ( ) ) ;
2018-07-25 03:11:03 +02:00
cells . write [ p_column ] . selectable = p_selectable ;
2014-02-10 02:10:30 +01:00
}
bool TreeItem : : is_selectable ( int p_column ) const {
2017-03-05 16:44:50 +01:00
ERR_FAIL_INDEX_V ( p_column , cells . size ( ) , false ) ;
2014-02-10 02:10:30 +01:00
return cells [ p_column ] . selectable ;
}
bool TreeItem : : is_selected ( int p_column ) {
2017-03-05 16:44:50 +01:00
ERR_FAIL_INDEX_V ( p_column , cells . size ( ) , false ) ;
2014-02-10 02:10:30 +01:00
return cells [ p_column ] . selectable & & cells [ p_column ] . selected ;
}
void TreeItem : : set_as_cursor ( int p_column ) {
2017-03-05 16:44:50 +01:00
ERR_FAIL_INDEX ( p_column , cells . size ( ) ) ;
2020-05-14 16:41:43 +02:00
if ( ! tree ) {
2014-02-10 02:10:30 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
if ( tree - > select_mode ! = Tree : : SELECT_MULTI ) {
2014-02-10 02:10:30 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2017-03-05 16:44:50 +01:00
tree - > selected_item = this ;
tree - > selected_col = p_column ;
2014-02-10 02:10:30 +01:00
tree - > update ( ) ;
}
void TreeItem : : select ( int p_column ) {
2017-03-05 16:44:50 +01:00
ERR_FAIL_INDEX ( p_column , cells . size ( ) ) ;
2014-02-10 02:10:30 +01:00
_cell_selected ( p_column ) ;
}
void TreeItem : : deselect ( int p_column ) {
2017-03-05 16:44:50 +01:00
ERR_FAIL_INDEX ( p_column , cells . size ( ) ) ;
2014-02-10 02:10:30 +01:00
_cell_deselected ( p_column ) ;
}
2019-06-11 20:43:37 +02:00
void TreeItem : : add_button ( int p_column , const Ref < Texture2D > & p_button , int p_id , bool p_disabled , const String & p_tooltip ) {
2017-03-05 16:44:50 +01:00
ERR_FAIL_INDEX ( p_column , cells . size ( ) ) ;
2014-02-10 02:10:30 +01:00
ERR_FAIL_COND ( ! p_button . is_valid ( ) ) ;
TreeItem : : Cell : : Button button ;
2017-03-05 16:44:50 +01:00
button . texture = p_button ;
2020-05-14 16:41:43 +02:00
if ( p_id < 0 ) {
2017-03-05 16:44:50 +01:00
p_id = cells [ p_column ] . buttons . size ( ) ;
2020-05-14 16:41:43 +02:00
}
2017-03-05 16:44:50 +01:00
button . id = p_id ;
button . disabled = p_disabled ;
2017-04-24 21:41:17 +02:00
button . tooltip = p_tooltip ;
2018-07-25 03:11:03 +02:00
cells . write [ p_column ] . buttons . push_back ( button ) ;
2021-09-24 10:11:44 +02:00
cells . write [ p_column ] . cached_minimum_size_dirty = true ;
2014-02-10 02:10:30 +01:00
_changed_notify ( p_column ) ;
}
int TreeItem : : get_button_count ( int p_column ) const {
2017-03-05 16:44:50 +01:00
ERR_FAIL_INDEX_V ( p_column , cells . size ( ) , - 1 ) ;
2014-02-10 02:10:30 +01:00
return cells [ p_column ] . buttons . size ( ) ;
}
2020-05-14 14:29:06 +02:00
2019-06-11 20:43:37 +02:00
Ref < Texture2D > TreeItem : : get_button ( int p_column , int p_idx ) const {
ERR_FAIL_INDEX_V ( p_column , cells . size ( ) , Ref < Texture2D > ( ) ) ;
ERR_FAIL_INDEX_V ( p_idx , cells [ p_column ] . buttons . size ( ) , Ref < Texture2D > ( ) ) ;
2014-02-10 02:10:30 +01:00
return cells [ p_column ] . buttons [ p_idx ] . texture ;
}
2020-05-14 14:29:06 +02:00
2019-09-04 16:47:47 +02:00
String TreeItem : : get_button_tooltip ( int p_column , int p_idx ) const {
ERR_FAIL_INDEX_V ( p_column , cells . size ( ) , String ( ) ) ;
ERR_FAIL_INDEX_V ( p_idx , cells [ p_column ] . buttons . size ( ) , String ( ) ) ;
return cells [ p_column ] . buttons [ p_idx ] . tooltip ;
}
2020-05-14 14:29:06 +02:00
2017-03-05 16:44:50 +01:00
void TreeItem : : erase_button ( int p_column , int p_idx ) {
ERR_FAIL_INDEX ( p_column , cells . size ( ) ) ;
ERR_FAIL_INDEX ( p_idx , cells [ p_column ] . buttons . size ( ) ) ;
2021-07-04 00:17:03 +02:00
cells . write [ p_column ] . buttons . remove_at ( p_idx ) ;
2014-02-10 02:10:30 +01:00
_changed_notify ( p_column ) ;
}
2017-03-05 16:44:50 +01:00
int TreeItem : : get_button_by_id ( int p_column , int p_id ) const {
ERR_FAIL_INDEX_V ( p_column , cells . size ( ) , - 1 ) ;
for ( int i = 0 ; i < cells [ p_column ] . buttons . size ( ) ; i + + ) {
2020-05-14 16:41:43 +02:00
if ( cells [ p_column ] . buttons [ i ] . id = = p_id ) {
2014-02-10 02:10:30 +01:00
return i ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
}
return - 1 ;
}
2016-02-03 00:44:42 +01:00
2019-06-11 20:43:37 +02:00
void TreeItem : : set_button ( int p_column , int p_idx , const Ref < Texture2D > & p_button ) {
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND ( p_button . is_null ( ) ) ;
ERR_FAIL_INDEX ( p_column , cells . size ( ) ) ;
ERR_FAIL_INDEX ( p_idx , cells [ p_column ] . buttons . size ( ) ) ;
2018-07-25 03:11:03 +02:00
cells . write [ p_column ] . buttons . write [ p_idx ] . texture = p_button ;
2021-09-24 10:11:44 +02:00
cells . write [ p_column ] . cached_minimum_size_dirty = true ;
2014-02-10 02:10:30 +01:00
_changed_notify ( p_column ) ;
}
2017-03-05 16:44:50 +01:00
void TreeItem : : set_button_color ( int p_column , int p_idx , const Color & p_color ) {
ERR_FAIL_INDEX ( p_column , cells . size ( ) ) ;
ERR_FAIL_INDEX ( p_idx , cells [ p_column ] . buttons . size ( ) ) ;
2018-07-25 03:11:03 +02:00
cells . write [ p_column ] . buttons . write [ p_idx ] . color = p_color ;
2016-12-28 14:12:08 +01:00
_changed_notify ( p_column ) ;
}
2019-07-09 09:13:00 +02:00
void TreeItem : : set_button_disabled ( int p_column , int p_idx , bool p_disabled ) {
ERR_FAIL_INDEX ( p_column , cells . size ( ) ) ;
ERR_FAIL_INDEX ( p_idx , cells [ p_column ] . buttons . size ( ) ) ;
cells . write [ p_column ] . buttons . write [ p_idx ] . disabled = p_disabled ;
2021-09-24 10:11:44 +02:00
cells . write [ p_column ] . cached_minimum_size_dirty = true ;
2019-07-09 09:13:00 +02:00
_changed_notify ( p_column ) ;
}
bool TreeItem : : is_button_disabled ( int p_column , int p_idx ) const {
ERR_FAIL_INDEX_V ( p_column , cells . size ( ) , false ) ;
ERR_FAIL_INDEX_V ( p_idx , cells [ p_column ] . buttons . size ( ) , false ) ;
return cells [ p_column ] . buttons [ p_idx ] . disabled ;
}
2017-03-05 16:44:50 +01:00
void TreeItem : : set_editable ( int p_column , bool p_editable ) {
ERR_FAIL_INDEX ( p_column , cells . size ( ) ) ;
2021-09-24 10:11:44 +02:00
2018-07-25 03:11:03 +02:00
cells . write [ p_column ] . editable = p_editable ;
2021-09-24 10:11:44 +02:00
cells . write [ p_column ] . cached_minimum_size_dirty = true ;
2014-02-10 02:10:30 +01:00
_changed_notify ( p_column ) ;
}
bool TreeItem : : is_editable ( int p_column ) {
2017-03-05 16:44:50 +01:00
ERR_FAIL_INDEX_V ( p_column , cells . size ( ) , false ) ;
2014-02-10 02:10:30 +01:00
return cells [ p_column ] . editable ;
}
2017-03-05 16:44:50 +01:00
void TreeItem : : set_custom_color ( int p_column , const Color & p_color ) {
ERR_FAIL_INDEX ( p_column , cells . size ( ) ) ;
2018-07-25 03:11:03 +02:00
cells . write [ p_column ] . custom_color = true ;
cells . write [ p_column ] . color = p_color ;
2014-02-10 02:10:30 +01:00
_changed_notify ( p_column ) ;
}
2020-05-14 14:29:06 +02:00
2016-03-12 14:44:12 +01:00
Color TreeItem : : get_custom_color ( int p_column ) const {
2017-03-05 16:44:50 +01:00
ERR_FAIL_INDEX_V ( p_column , cells . size ( ) , Color ( ) ) ;
2020-05-14 16:41:43 +02:00
if ( ! cells [ p_column ] . custom_color ) {
2016-03-12 14:44:12 +01:00
return Color ( ) ;
2020-05-14 16:41:43 +02:00
}
2016-03-12 14:44:12 +01:00
return cells [ p_column ] . color ;
}
2020-05-14 14:29:06 +02:00
2014-02-10 02:10:30 +01:00
void TreeItem : : clear_custom_color ( int p_column ) {
2017-03-05 16:44:50 +01:00
ERR_FAIL_INDEX ( p_column , cells . size ( ) ) ;
2018-07-25 03:11:03 +02:00
cells . write [ p_column ] . custom_color = false ;
cells . write [ p_column ] . color = Color ( ) ;
2014-02-10 02:10:30 +01:00
_changed_notify ( p_column ) ;
}
2021-05-27 17:32:30 +02:00
void TreeItem : : set_custom_font ( int p_column , const Ref < Font > & p_font ) {
ERR_FAIL_INDEX ( p_column , cells . size ( ) ) ;
2021-09-24 10:11:44 +02:00
2021-05-27 17:32:30 +02:00
cells . write [ p_column ] . custom_font = p_font ;
2021-09-24 10:11:44 +02:00
cells . write [ p_column ] . cached_minimum_size_dirty = true ;
2021-05-27 17:32:30 +02:00
}
2020-12-27 14:30:33 +01:00
2021-05-27 17:32:30 +02:00
Ref < Font > TreeItem : : get_custom_font ( int p_column ) const {
ERR_FAIL_INDEX_V ( p_column , cells . size ( ) , Ref < Font > ( ) ) ;
return cells [ p_column ] . custom_font ;
}
2020-12-27 14:30:33 +01:00
void TreeItem : : set_custom_font_size ( int p_column , int p_font_size ) {
ERR_FAIL_INDEX ( p_column , cells . size ( ) ) ;
2021-09-24 10:11:44 +02:00
2020-12-27 14:30:33 +01:00
cells . write [ p_column ] . custom_font_size = p_font_size ;
2021-09-24 10:11:44 +02:00
cells . write [ p_column ] . cached_minimum_size_dirty = true ;
2020-12-27 14:30:33 +01:00
}
int TreeItem : : get_custom_font_size ( int p_column ) const {
ERR_FAIL_INDEX_V ( p_column , cells . size ( ) , - 1 ) ;
return cells [ p_column ] . custom_font_size ;
}
2017-03-05 16:44:50 +01:00
void TreeItem : : set_tooltip ( int p_column , const String & p_tooltip ) {
ERR_FAIL_INDEX ( p_column , cells . size ( ) ) ;
2018-07-25 03:11:03 +02:00
cells . write [ p_column ] . tooltip = p_tooltip ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
String TreeItem : : get_tooltip ( int p_column ) const {
ERR_FAIL_INDEX_V ( p_column , cells . size ( ) , " " ) ;
2014-02-10 02:10:30 +01:00
return cells [ p_column ] . tooltip ;
}
2017-03-05 16:44:50 +01:00
void TreeItem : : set_custom_bg_color ( int p_column , const Color & p_color , bool p_bg_outline ) {
ERR_FAIL_INDEX ( p_column , cells . size ( ) ) ;
2018-07-25 03:11:03 +02:00
cells . write [ p_column ] . custom_bg_color = true ;
cells . write [ p_column ] . custom_bg_outline = p_bg_outline ;
cells . write [ p_column ] . bg_color = p_color ;
2014-02-10 02:10:30 +01:00
_changed_notify ( p_column ) ;
}
void TreeItem : : clear_custom_bg_color ( int p_column ) {
2017-03-05 16:44:50 +01:00
ERR_FAIL_INDEX ( p_column , cells . size ( ) ) ;
2018-07-25 03:11:03 +02:00
cells . write [ p_column ] . custom_bg_color = false ;
cells . write [ p_column ] . bg_color = Color ( ) ;
2014-02-10 02:10:30 +01:00
_changed_notify ( p_column ) ;
}
Color TreeItem : : get_custom_bg_color ( int p_column ) const {
2017-03-05 16:44:50 +01:00
ERR_FAIL_INDEX_V ( p_column , cells . size ( ) , Color ( ) ) ;
2020-05-14 16:41:43 +02:00
if ( ! cells [ p_column ] . custom_bg_color ) {
2014-02-10 02:10:30 +01:00
return Color ( ) ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
return cells [ p_column ] . bg_color ;
}
2017-06-05 01:35:08 +02:00
void TreeItem : : set_custom_as_button ( int p_column , bool p_button ) {
ERR_FAIL_INDEX ( p_column , cells . size ( ) ) ;
2021-09-24 10:11:44 +02:00
2018-07-25 03:11:03 +02:00
cells . write [ p_column ] . custom_button = p_button ;
2021-09-24 10:11:44 +02:00
cells . write [ p_column ] . cached_minimum_size_dirty = true ;
2017-06-05 01:35:08 +02:00
}
bool TreeItem : : is_custom_set_as_button ( int p_column ) const {
ERR_FAIL_INDEX_V ( p_column , cells . size ( ) , false ) ;
return cells [ p_column ] . custom_button ;
}
2021-11-25 03:58:47 +01:00
void TreeItem : : set_text_alignment ( int p_column , HorizontalAlignment p_alignment ) {
2017-06-25 22:30:28 +02:00
ERR_FAIL_INDEX ( p_column , cells . size ( ) ) ;
2021-09-24 10:11:44 +02:00
2021-11-25 03:58:47 +01:00
cells . write [ p_column ] . text_alignment = p_alignment ;
2021-09-24 10:11:44 +02:00
cells . write [ p_column ] . cached_minimum_size_dirty = true ;
2017-06-25 22:30:28 +02:00
_changed_notify ( p_column ) ;
}
2021-11-25 03:58:47 +01:00
HorizontalAlignment TreeItem : : get_text_alignment ( int p_column ) const {
ERR_FAIL_INDEX_V ( p_column , cells . size ( ) , HORIZONTAL_ALIGNMENT_LEFT ) ;
return cells [ p_column ] . text_alignment ;
2017-06-25 22:30:28 +02:00
}
void TreeItem : : set_expand_right ( int p_column , bool p_enable ) {
ERR_FAIL_INDEX ( p_column , cells . size ( ) ) ;
2021-09-24 10:11:44 +02:00
2018-07-25 03:11:03 +02:00
cells . write [ p_column ] . expand_right = p_enable ;
2021-09-24 10:11:44 +02:00
cells . write [ p_column ] . cached_minimum_size_dirty = true ;
2017-06-25 22:30:28 +02:00
_changed_notify ( p_column ) ;
}
bool TreeItem : : get_expand_right ( int p_column ) const {
ERR_FAIL_INDEX_V ( p_column , cells . size ( ) , false ) ;
return cells [ p_column ] . expand_right ;
}
void TreeItem : : set_disable_folding ( bool p_disable ) {
disable_folding = p_disable ;
2021-09-24 10:11:44 +02:00
2022-01-27 17:34:33 +01:00
for ( Cell & c : cells ) {
2021-09-24 10:11:44 +02:00
c . cached_minimum_size_dirty = true ;
2022-01-27 17:34:33 +01:00
}
2021-09-24 10:11:44 +02:00
2017-06-25 22:30:28 +02:00
_changed_notify ( 0 ) ;
}
bool TreeItem : : is_folding_disabled ( ) const {
return disable_folding ;
}
2021-06-28 15:40:56 +02:00
Size2 TreeItem : : get_minimum_size ( int p_column ) {
ERR_FAIL_INDEX_V ( p_column , cells . size ( ) , Size2 ( ) ) ;
Tree * tree = get_tree ( ) ;
ERR_FAIL_COND_V ( ! tree , Size2 ( ) ) ;
2021-09-24 10:11:44 +02:00
const TreeItem : : Cell & cell = cells [ p_column ] ;
2021-06-28 15:40:56 +02:00
2021-09-24 10:11:44 +02:00
if ( cell . cached_minimum_size_dirty ) {
Size2 size ;
2021-06-28 15:40:56 +02:00
2021-09-01 16:26:41 +02:00
// Text.
if ( ! cell . text . is_empty ( ) ) {
if ( cell . dirty ) {
tree - > update_item_cell ( this , p_column ) ;
}
Size2 text_size = cell . text_buf - > get_size ( ) ;
size . width + = text_size . width ;
size . height = MAX ( size . height , text_size . height ) ;
2021-06-28 15:40:56 +02:00
}
2021-09-01 16:26:41 +02:00
// Icon.
if ( cell . mode = = CELL_MODE_CHECK ) {
size . width + = tree - > cache . checked - > get_width ( ) + tree - > cache . hseparation ;
}
if ( cell . icon . is_valid ( ) ) {
Size2i icon_size = cell . get_icon_size ( ) ;
if ( cell . icon_max_w > 0 & & icon_size . width > cell . icon_max_w ) {
icon_size . width = cell . icon_max_w ;
}
size . width + = icon_size . width + tree - > cache . hseparation ;
size . height = MAX ( size . height , icon_size . height ) ;
2021-06-28 15:40:56 +02:00
}
2021-09-01 16:26:41 +02:00
// Buttons.
for ( int i = 0 ; i < cell . buttons . size ( ) ; i + + ) {
Ref < Texture2D > texture = cell . buttons [ i ] . texture ;
if ( texture . is_valid ( ) ) {
Size2 button_size = texture - > get_size ( ) + tree - > cache . button_pressed - > get_minimum_size ( ) ;
size . width + = button_size . width ;
size . height = MAX ( size . height , button_size . height ) ;
}
2021-06-28 15:40:56 +02:00
}
2021-09-01 16:26:41 +02:00
if ( cell . buttons . size ( ) > = 2 ) {
size . width + = ( cell . buttons . size ( ) - 1 ) * tree - > cache . button_margin ;
}
2021-09-24 10:11:44 +02:00
cells . write [ p_column ] . cached_minimum_size = size ;
cells . write [ p_column ] . cached_minimum_size_dirty = false ;
2021-06-28 15:40:56 +02:00
}
2021-09-24 10:11:44 +02:00
return cell . cached_minimum_size ;
2021-06-28 15:40:56 +02:00
}
2020-02-19 20:27:19 +01:00
Variant TreeItem : : _call_recursive_bind ( const Variant * * p_args , int p_argcount , Callable : : CallError & r_error ) {
2018-10-07 18:25:57 +02:00
if ( p_argcount < 1 ) {
2020-02-19 20:27:19 +01:00
r_error . error = Callable : : CallError : : CALL_ERROR_TOO_FEW_ARGUMENTS ;
2018-10-07 18:25:57 +02:00
r_error . argument = 0 ;
return Variant ( ) ;
}
2020-02-20 22:58:05 +01:00
if ( p_args [ 0 ] - > get_type ( ) ! = Variant : : STRING & & p_args [ 0 ] - > get_type ( ) ! = Variant : : STRING_NAME ) {
2020-02-19 20:27:19 +01:00
r_error . error = Callable : : CallError : : CALL_ERROR_INVALID_ARGUMENT ;
2018-10-07 18:25:57 +02:00
r_error . argument = 0 ;
2020-02-20 22:58:05 +01:00
r_error . expected = Variant : : STRING_NAME ;
2018-10-07 18:25:57 +02:00
return Variant ( ) ;
}
StringName method = * p_args [ 0 ] ;
call_recursive ( method , & p_args [ 1 ] , p_argcount - 1 , r_error ) ;
return Variant ( ) ;
}
2020-02-19 20:27:19 +01:00
void recursive_call_aux ( TreeItem * p_item , const StringName & p_method , const Variant * * p_args , int p_argcount , Callable : : CallError & r_error ) {
2018-10-07 18:25:57 +02:00
if ( ! p_item ) {
return ;
}
p_item - > call ( p_method , p_args , p_argcount , r_error ) ;
2021-03-07 21:07:30 +01:00
TreeItem * c = p_item - > get_first_child ( ) ;
2018-10-07 18:25:57 +02:00
while ( c ) {
recursive_call_aux ( c , p_method , p_args , p_argcount , r_error ) ;
c = c - > get_next ( ) ;
}
}
2020-02-19 20:27:19 +01:00
void TreeItem : : call_recursive ( const StringName & p_method , const Variant * * p_args , int p_argcount , Callable : : CallError & r_error ) {
2018-10-07 18:25:57 +02:00
recursive_call_aux ( this , p_method , p_args , p_argcount , r_error ) ;
}
2014-02-10 02:10:30 +01:00
void TreeItem : : _bind_methods ( ) {
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_cell_mode " , " column " , " mode " ) , & TreeItem : : set_cell_mode ) ;
ClassDB : : bind_method ( D_METHOD ( " get_cell_mode " , " column " ) , & TreeItem : : get_cell_mode ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_checked " , " column " , " checked " ) , & TreeItem : : set_checked ) ;
2021-07-22 22:34:54 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_indeterminate " , " column " , " indeterminate " ) , & TreeItem : : set_indeterminate ) ;
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " is_checked " , " column " ) , & TreeItem : : is_checked ) ;
2021-07-22 22:34:54 +02:00
ClassDB : : bind_method ( D_METHOD ( " is_indeterminate " , " column " ) , & TreeItem : : is_indeterminate ) ;
2014-02-10 02:10:30 +01:00
2021-09-17 17:50:24 +02:00
ClassDB : : bind_method ( D_METHOD ( " propagate_check " , " column " , " emit_signal " ) , & TreeItem : : propagate_check , DEFVAL ( true ) ) ;
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_text " , " column " , " text " ) , & TreeItem : : set_text ) ;
ClassDB : : bind_method ( D_METHOD ( " get_text " , " column " ) , & TreeItem : : get_text ) ;
2014-02-10 02:10:30 +01:00
2020-09-03 13:22:16 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_text_direction " , " column " , " direction " ) , & TreeItem : : set_text_direction ) ;
ClassDB : : bind_method ( D_METHOD ( " get_text_direction " , " column " ) , & TreeItem : : get_text_direction ) ;
ClassDB : : bind_method ( D_METHOD ( " set_opentype_feature " , " column " , " tag " , " value " ) , & TreeItem : : set_opentype_feature ) ;
ClassDB : : bind_method ( D_METHOD ( " get_opentype_feature " , " column " , " tag " ) , & TreeItem : : get_opentype_feature ) ;
ClassDB : : bind_method ( D_METHOD ( " clear_opentype_features " , " column " ) , & TreeItem : : clear_opentype_features ) ;
ClassDB : : bind_method ( D_METHOD ( " set_structured_text_bidi_override " , " column " , " parser " ) , & TreeItem : : set_structured_text_bidi_override ) ;
ClassDB : : bind_method ( D_METHOD ( " get_structured_text_bidi_override " , " column " ) , & TreeItem : : get_structured_text_bidi_override ) ;
ClassDB : : bind_method ( D_METHOD ( " set_structured_text_bidi_override_options " , " column " , " args " ) , & TreeItem : : set_structured_text_bidi_override_options ) ;
ClassDB : : bind_method ( D_METHOD ( " get_structured_text_bidi_override_options " , " column " ) , & TreeItem : : get_structured_text_bidi_override_options ) ;
ClassDB : : bind_method ( D_METHOD ( " set_language " , " column " , " language " ) , & TreeItem : : set_language ) ;
ClassDB : : bind_method ( D_METHOD ( " get_language " , " column " ) , & TreeItem : : get_language ) ;
2020-05-05 20:51:13 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_suffix " , " column " , " text " ) , & TreeItem : : set_suffix ) ;
ClassDB : : bind_method ( D_METHOD ( " get_suffix " , " column " ) , & TreeItem : : get_suffix ) ;
2017-08-09 13:19:41 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_icon " , " column " , " texture " ) , & TreeItem : : set_icon ) ;
ClassDB : : bind_method ( D_METHOD ( " get_icon " , " column " ) , & TreeItem : : get_icon ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_icon_region " , " column " , " region " ) , & TreeItem : : set_icon_region ) ;
ClassDB : : bind_method ( D_METHOD ( " get_icon_region " , " column " ) , & TreeItem : : get_icon_region ) ;
2015-08-31 00:37:23 +02:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_icon_max_width " , " column " , " width " ) , & TreeItem : : set_icon_max_width ) ;
ClassDB : : bind_method ( D_METHOD ( " get_icon_max_width " , " column " ) , & TreeItem : : get_icon_max_width ) ;
2014-02-10 02:10:30 +01:00
2019-08-24 17:13:48 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_icon_modulate " , " column " , " modulate " ) , & TreeItem : : set_icon_modulate ) ;
ClassDB : : bind_method ( D_METHOD ( " get_icon_modulate " , " column " ) , & TreeItem : : get_icon_modulate ) ;
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_range " , " column " , " value " ) , & TreeItem : : set_range ) ;
ClassDB : : bind_method ( D_METHOD ( " get_range " , " column " ) , & TreeItem : : get_range ) ;
ClassDB : : bind_method ( D_METHOD ( " set_range_config " , " column " , " min " , " max " , " step " , " expr " ) , & TreeItem : : set_range_config , DEFVAL ( false ) ) ;
ClassDB : : bind_method ( D_METHOD ( " get_range_config " , " column " ) , & TreeItem : : _get_range_config ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_metadata " , " column " , " meta " ) , & TreeItem : : set_metadata ) ;
ClassDB : : bind_method ( D_METHOD ( " get_metadata " , " column " ) , & TreeItem : : get_metadata ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_custom_draw " , " column " , " object " , " callback " ) , & TreeItem : : set_custom_draw ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_collapsed " , " enable " ) , & TreeItem : : set_collapsed ) ;
ClassDB : : bind_method ( D_METHOD ( " is_collapsed " ) , & TreeItem : : is_collapsed ) ;
2014-02-10 02:10:30 +01:00
2021-03-19 13:57:52 +01:00
ClassDB : : bind_method ( D_METHOD ( " uncollapse_tree " ) , & TreeItem : : uncollapse_tree ) ;
2017-09-05 14:31:07 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_custom_minimum_height " , " height " ) , & TreeItem : : set_custom_minimum_height ) ;
ClassDB : : bind_method ( D_METHOD ( " get_custom_minimum_height " ) , & TreeItem : : get_custom_minimum_height ) ;
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_selectable " , " column " , " selectable " ) , & TreeItem : : set_selectable ) ;
ClassDB : : bind_method ( D_METHOD ( " is_selectable " , " column " ) , & TreeItem : : is_selectable ) ;
2015-08-31 00:37:23 +02:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " is_selected " , " column " ) , & TreeItem : : is_selected ) ;
ClassDB : : bind_method ( D_METHOD ( " select " , " column " ) , & TreeItem : : select ) ;
ClassDB : : bind_method ( D_METHOD ( " deselect " , " column " ) , & TreeItem : : deselect ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_editable " , " column " , " enabled " ) , & TreeItem : : set_editable ) ;
ClassDB : : bind_method ( D_METHOD ( " is_editable " , " column " ) , & TreeItem : : is_editable ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_custom_color " , " column " , " color " ) , & TreeItem : : set_custom_color ) ;
2019-10-06 22:07:50 +02:00
ClassDB : : bind_method ( D_METHOD ( " get_custom_color " , " column " ) , & TreeItem : : get_custom_color ) ;
2021-05-27 17:32:30 +02:00
ClassDB : : bind_method ( D_METHOD ( " clear_custom_color " , " column " ) , & TreeItem : : clear_custom_color ) ;
ClassDB : : bind_method ( D_METHOD ( " set_custom_font " , " column " , " font " ) , & TreeItem : : set_custom_font ) ;
ClassDB : : bind_method ( D_METHOD ( " get_custom_font " , " column " ) , & TreeItem : : get_custom_font ) ;
2014-02-10 02:10:30 +01:00
2020-12-27 14:30:33 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_custom_font_size " , " column " , " font_size " ) , & TreeItem : : set_custom_font_size ) ;
ClassDB : : bind_method ( D_METHOD ( " get_custom_font_size " , " column " ) , & TreeItem : : get_custom_font_size ) ;
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_custom_bg_color " , " column " , " color " , " just_outline " ) , & TreeItem : : set_custom_bg_color , DEFVAL ( false ) ) ;
ClassDB : : bind_method ( D_METHOD ( " clear_custom_bg_color " , " column " ) , & TreeItem : : clear_custom_bg_color ) ;
ClassDB : : bind_method ( D_METHOD ( " get_custom_bg_color " , " column " ) , & TreeItem : : get_custom_bg_color ) ;
2014-02-10 02:10:30 +01:00
2017-06-05 01:35:08 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_custom_as_button " , " column " , " enable " ) , & TreeItem : : set_custom_as_button ) ;
ClassDB : : bind_method ( D_METHOD ( " is_custom_set_as_button " , " column " ) , & TreeItem : : is_custom_set_as_button ) ;
2017-08-09 13:19:41 +02:00
ClassDB : : bind_method ( D_METHOD ( " add_button " , " column " , " button " , " button_idx " , " disabled " , " tooltip " ) , & TreeItem : : add_button , DEFVAL ( - 1 ) , DEFVAL ( false ) , DEFVAL ( " " ) ) ;
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " get_button_count " , " column " ) , & TreeItem : : get_button_count ) ;
2019-09-27 22:16:32 +02:00
ClassDB : : bind_method ( D_METHOD ( " get_button_tooltip " , " column " , " button_idx " ) , & TreeItem : : get_button_tooltip ) ;
2017-08-09 13:19:41 +02:00
ClassDB : : bind_method ( D_METHOD ( " get_button " , " column " , " button_idx " ) , & TreeItem : : get_button ) ;
ClassDB : : bind_method ( D_METHOD ( " set_button " , " column " , " button_idx " , " button " ) , & TreeItem : : set_button ) ;
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " erase_button " , " column " , " button_idx " ) , & TreeItem : : erase_button ) ;
2019-07-09 09:13:00 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_button_disabled " , " column " , " button_idx " , " disabled " ) , & TreeItem : : set_button_disabled ) ;
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " is_button_disabled " , " column " , " button_idx " ) , & TreeItem : : is_button_disabled ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_tooltip " , " column " , " tooltip " ) , & TreeItem : : set_tooltip ) ;
ClassDB : : bind_method ( D_METHOD ( " get_tooltip " , " column " ) , & TreeItem : : get_tooltip ) ;
2021-11-25 03:58:47 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_text_alignment " , " column " , " text_alignment " ) , & TreeItem : : set_text_alignment ) ;
ClassDB : : bind_method ( D_METHOD ( " get_text_alignment " , " column " ) , & TreeItem : : get_text_alignment ) ;
2021-03-07 21:07:30 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_expand_right " , " column " , " enable " ) , & TreeItem : : set_expand_right ) ;
ClassDB : : bind_method ( D_METHOD ( " get_expand_right " , " column " ) , & TreeItem : : get_expand_right ) ;
2014-02-10 02:10:30 +01:00
2017-06-25 22:30:28 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_disable_folding " , " disable " ) , & TreeItem : : set_disable_folding ) ;
ClassDB : : bind_method ( D_METHOD ( " is_folding_disabled " ) , & TreeItem : : is_folding_disabled ) ;
2021-03-07 21:07:30 +01:00
ClassDB : : bind_method ( D_METHOD ( " create_child " , " idx " ) , & TreeItem : : create_child , DEFVAL ( - 1 ) ) ;
ClassDB : : bind_method ( D_METHOD ( " get_tree " ) , & TreeItem : : get_tree ) ;
ClassDB : : bind_method ( D_METHOD ( " get_next " ) , & TreeItem : : get_next ) ;
ClassDB : : bind_method ( D_METHOD ( " get_prev " ) , & TreeItem : : get_prev ) ;
ClassDB : : bind_method ( D_METHOD ( " get_parent " ) , & TreeItem : : get_parent ) ;
ClassDB : : bind_method ( D_METHOD ( " get_first_child " ) , & TreeItem : : get_first_child ) ;
ClassDB : : bind_method ( D_METHOD ( " get_next_visible " , " wrap " ) , & TreeItem : : get_next_visible , DEFVAL ( false ) ) ;
ClassDB : : bind_method ( D_METHOD ( " get_prev_visible " , " wrap " ) , & TreeItem : : get_prev_visible , DEFVAL ( false ) ) ;
ClassDB : : bind_method ( D_METHOD ( " get_child " , " idx " ) , & TreeItem : : get_child ) ;
ClassDB : : bind_method ( D_METHOD ( " get_child_count " ) , & TreeItem : : get_child_count ) ;
ClassDB : : bind_method ( D_METHOD ( " get_children " ) , & TreeItem : : get_children ) ;
ClassDB : : bind_method ( D_METHOD ( " get_index " ) , & TreeItem : : get_index ) ;
ClassDB : : bind_method ( D_METHOD ( " move_before " , " item " ) , & TreeItem : : _move_before ) ;
ClassDB : : bind_method ( D_METHOD ( " move_after " , " item " ) , & TreeItem : : _move_after ) ;
ClassDB : : bind_method ( D_METHOD ( " remove_child " , " child " ) , & TreeItem : : _remove_child ) ;
2018-10-07 18:25:57 +02:00
{
MethodInfo mi ;
mi . name = " call_recursive " ;
2020-02-20 22:58:05 +01:00
mi . arguments . push_back ( PropertyInfo ( Variant : : STRING_NAME , " method " ) ) ;
2018-10-07 18:25:57 +02:00
ClassDB : : bind_vararg_method ( METHOD_FLAGS_DEFAULT , " call_recursive " , & TreeItem : : _call_recursive_bind , mi ) ;
}
2018-01-11 23:35:12 +01:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " collapsed " ) , " set_collapsed " , " is_collapsed " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " disable_folding " ) , " set_disable_folding " , " is_folding_disabled " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : INT , " custom_minimum_height " , PROPERTY_HINT_RANGE , " 0,1000,1 " ) , " set_custom_minimum_height " , " get_custom_minimum_height " ) ;
2017-08-20 17:45:01 +02:00
BIND_ENUM_CONSTANT ( CELL_MODE_STRING ) ;
BIND_ENUM_CONSTANT ( CELL_MODE_CHECK ) ;
BIND_ENUM_CONSTANT ( CELL_MODE_RANGE ) ;
BIND_ENUM_CONSTANT ( CELL_MODE_ICON ) ;
BIND_ENUM_CONSTANT ( CELL_MODE_CUSTOM ) ;
2014-02-10 02:10:30 +01:00
}
void TreeItem : : clear_children ( ) {
2021-03-07 21:07:30 +01:00
TreeItem * c = first_child ;
2014-02-10 02:10:30 +01:00
while ( c ) {
2017-03-05 16:44:50 +01:00
TreeItem * aux = c ;
c = c - > get_next ( ) ;
2020-04-02 01:20:12 +02:00
aux - > parent = nullptr ; // so it won't try to recursively autoremove from me in here
2017-03-05 16:44:50 +01:00
memdelete ( aux ) ;
2014-02-10 02:10:30 +01:00
}
2021-03-07 21:07:30 +01:00
first_child = nullptr ;
2014-02-10 02:10:30 +01:00
} ;
TreeItem : : TreeItem ( Tree * p_tree ) {
2017-03-05 16:44:50 +01:00
tree = p_tree ;
2014-02-10 02:10:30 +01:00
}
TreeItem : : ~ TreeItem ( ) {
2021-03-07 21:07:30 +01:00
_unlink_from_tree ( ) ;
prev = nullptr ;
2014-02-10 02:10:30 +01:00
clear_children ( ) ;
2021-03-07 21:07:30 +01:00
_change_tree ( nullptr ) ;
2014-02-10 02:10:30 +01:00
}
/**********************************************/
/**********************************************/
/**********************************************/
/**********************************************/
/**********************************************/
/**********************************************/
void Tree : : update_cache ( ) {
2021-07-17 23:22:52 +02:00
cache . font = get_theme_font ( SNAME ( " font " ) ) ;
cache . font_size = get_theme_font_size ( SNAME ( " font_size " ) ) ;
cache . tb_font = get_theme_font ( SNAME ( " title_button_font " ) ) ;
cache . tb_font_size = get_theme_font_size ( SNAME ( " title_button_font_size " ) ) ;
cache . bg = get_theme_stylebox ( SNAME ( " bg " ) ) ;
cache . selected = get_theme_stylebox ( SNAME ( " selected " ) ) ;
cache . selected_focus = get_theme_stylebox ( SNAME ( " selected_focus " ) ) ;
cache . cursor = get_theme_stylebox ( SNAME ( " cursor " ) ) ;
cache . cursor_unfocus = get_theme_stylebox ( SNAME ( " cursor_unfocused " ) ) ;
cache . button_pressed = get_theme_stylebox ( SNAME ( " button_pressed " ) ) ;
cache . checked = get_theme_icon ( SNAME ( " checked " ) ) ;
cache . unchecked = get_theme_icon ( SNAME ( " unchecked " ) ) ;
2021-07-22 22:34:54 +02:00
cache . indeterminate = get_theme_icon ( SNAME ( " indeterminate " ) ) ;
2020-09-03 13:22:16 +02:00
if ( is_layout_rtl ( ) ) {
2021-07-17 23:22:52 +02:00
cache . arrow_collapsed = get_theme_icon ( SNAME ( " arrow_collapsed_mirrored " ) ) ;
2020-09-03 13:22:16 +02:00
} else {
2021-07-17 23:22:52 +02:00
cache . arrow_collapsed = get_theme_icon ( SNAME ( " arrow_collapsed " ) ) ;
}
cache . arrow = get_theme_icon ( SNAME ( " arrow " ) ) ;
cache . select_arrow = get_theme_icon ( SNAME ( " select_arrow " ) ) ;
cache . updown = get_theme_icon ( SNAME ( " updown " ) ) ;
cache . custom_button = get_theme_stylebox ( SNAME ( " custom_button " ) ) ;
cache . custom_button_hover = get_theme_stylebox ( SNAME ( " custom_button_hover " ) ) ;
cache . custom_button_pressed = get_theme_stylebox ( SNAME ( " custom_button_pressed " ) ) ;
cache . custom_button_font_highlight = get_theme_color ( SNAME ( " custom_button_font_highlight " ) ) ;
cache . font_color = get_theme_color ( SNAME ( " font_color " ) ) ;
cache . font_selected_color = get_theme_color ( SNAME ( " font_selected_color " ) ) ;
cache . drop_position_color = get_theme_color ( SNAME ( " drop_position_color " ) ) ;
cache . hseparation = get_theme_constant ( SNAME ( " hseparation " ) ) ;
cache . vseparation = get_theme_constant ( SNAME ( " vseparation " ) ) ;
cache . item_margin = get_theme_constant ( SNAME ( " item_margin " ) ) ;
cache . button_margin = get_theme_constant ( SNAME ( " button_margin " ) ) ;
cache . font_outline_color = get_theme_color ( SNAME ( " font_outline_color " ) ) ;
cache . font_outline_size = get_theme_constant ( SNAME ( " outline_size " ) ) ;
cache . draw_guides = get_theme_constant ( SNAME ( " draw_guides " ) ) ;
cache . guide_color = get_theme_color ( SNAME ( " guide_color " ) ) ;
cache . draw_relationship_lines = get_theme_constant ( SNAME ( " draw_relationship_lines " ) ) ;
cache . relationship_line_width = get_theme_constant ( SNAME ( " relationship_line_width " ) ) ;
cache . parent_hl_line_width = get_theme_constant ( SNAME ( " parent_hl_line_width " ) ) ;
cache . children_hl_line_width = get_theme_constant ( SNAME ( " children_hl_line_width " ) ) ;
cache . parent_hl_line_margin = get_theme_constant ( SNAME ( " parent_hl_line_margin " ) ) ;
cache . relationship_line_color = get_theme_color ( SNAME ( " relationship_line_color " ) ) ;
cache . parent_hl_line_color = get_theme_color ( SNAME ( " parent_hl_line_color " ) ) ;
cache . children_hl_line_color = get_theme_color ( SNAME ( " children_hl_line_color " ) ) ;
cache . scroll_border = get_theme_constant ( SNAME ( " scroll_border " ) ) ;
cache . scroll_speed = get_theme_constant ( SNAME ( " scroll_speed " ) ) ;
cache . title_button = get_theme_stylebox ( SNAME ( " title_button_normal " ) ) ;
cache . title_button_pressed = get_theme_stylebox ( SNAME ( " title_button_pressed " ) ) ;
cache . title_button_hover = get_theme_stylebox ( SNAME ( " title_button_hover " ) ) ;
cache . title_button_color = get_theme_color ( SNAME ( " title_button_color " ) ) ;
2014-02-10 02:10:30 +01:00
2021-10-02 22:07:42 +02:00
cache . base_scale = get_theme_default_base_scale ( ) ;
2020-09-03 13:22:16 +02:00
v_scroll - > set_custom_step ( cache . font - > get_height ( cache . font_size ) ) ;
2014-02-10 02:10:30 +01:00
}
int Tree : : compute_item_height ( TreeItem * p_item ) const {
2020-05-14 16:41:43 +02:00
if ( p_item = = root & & hide_root ) {
2014-02-10 02:10:30 +01:00
return 0 ;
2020-05-14 16:41:43 +02:00
}
2015-08-31 00:37:23 +02:00
2018-01-06 19:48:54 +01:00
ERR_FAIL_COND_V ( cache . font . is_null ( ) , 0 ) ;
2020-09-03 13:22:16 +02:00
int height = 0 ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < columns . size ( ) ; i + + ) {
2020-09-03 13:22:16 +02:00
if ( p_item - > cells [ i ] . dirty ) {
const_cast < Tree * > ( this ) - > update_item_cell ( p_item , i ) ;
}
height = MAX ( height , p_item - > cells [ i ] . text_buf - > get_size ( ) . y ) ;
2017-03-05 16:44:50 +01:00
for ( int j = 0 ; j < p_item - > cells [ i ] . buttons . size ( ) ; j + + ) {
Size2i s ; // = cache.button_pressed->get_minimum_size();
s + = p_item - > cells [ i ] . buttons [ j ] . texture - > get_size ( ) ;
2020-05-14 16:41:43 +02:00
if ( s . height > height ) {
2017-03-05 16:44:50 +01:00
height = s . height ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
switch ( p_item - > cells [ i ] . mode ) {
2014-02-10 02:10:30 +01:00
case TreeItem : : CELL_MODE_CHECK : {
int check_icon_h = cache . checked - > get_height ( ) ;
2020-05-14 16:41:43 +02:00
if ( height < check_icon_h ) {
2017-03-05 16:44:50 +01:00
height = check_icon_h ;
2020-05-14 16:41:43 +02:00
}
2020-02-22 20:47:50 +01:00
[[fallthrough]] ;
2014-02-10 02:10:30 +01:00
}
case TreeItem : : CELL_MODE_STRING :
case TreeItem : : CELL_MODE_CUSTOM :
case TreeItem : : CELL_MODE_ICON : {
2019-06-11 20:43:37 +02:00
Ref < Texture2D > icon = p_item - > cells [ i ] . icon ;
2014-02-10 02:10:30 +01:00
if ( ! icon . is_null ( ) ) {
Size2i s = p_item - > cells [ i ] . get_icon_size ( ) ;
2017-03-05 16:44:50 +01:00
if ( p_item - > cells [ i ] . icon_max_w > 0 & & s . width > p_item - > cells [ i ] . icon_max_w ) {
s . height = s . height * p_item - > cells [ i ] . icon_max_w / s . width ;
2014-02-10 02:10:30 +01:00
}
2020-05-14 16:41:43 +02:00
if ( s . height > height ) {
2017-03-05 16:44:50 +01:00
height = s . height ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
}
2017-06-05 01:35:08 +02:00
if ( p_item - > cells [ i ] . mode = = TreeItem : : CELL_MODE_CUSTOM & & p_item - > cells [ i ] . custom_button ) {
height + = cache . custom_button - > get_minimum_size ( ) . height ;
}
2015-08-31 00:37:23 +02:00
2014-02-10 02:10:30 +01:00
} break ;
2019-04-09 17:08:36 +02:00
default : {
}
2014-02-10 02:10:30 +01:00
}
}
2017-09-05 14:31:07 +02:00
int item_min_height = p_item - > get_custom_minimum_height ( ) ;
2020-05-14 16:41:43 +02:00
if ( height < item_min_height ) {
2017-09-05 14:31:07 +02:00
height = item_min_height ;
2020-05-14 16:41:43 +02:00
}
2015-08-31 00:37:23 +02:00
2014-02-10 02:10:30 +01:00
height + = cache . vseparation ;
2015-08-31 00:37:23 +02:00
2014-02-10 02:10:30 +01:00
return height ;
}
int Tree : : get_item_height ( TreeItem * p_item ) const {
2017-03-05 16:44:50 +01:00
int height = compute_item_height ( p_item ) ;
height + = cache . vseparation ;
2014-02-10 02:10:30 +01:00
2018-01-18 21:37:17 +01:00
if ( ! p_item - > collapsed ) { /* if not collapsed, check the children */
2014-02-10 02:10:30 +01:00
2021-03-07 21:07:30 +01:00
TreeItem * c = p_item - > first_child ;
2014-02-10 02:10:30 +01:00
while ( c ) {
2017-03-05 16:44:50 +01:00
height + = get_item_height ( c ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
c = c - > next ;
2014-02-10 02:10:30 +01:00
}
}
return height ;
}
2020-12-25 22:45:28 +01:00
void Tree : : draw_item_rect ( TreeItem : : Cell & p_cell , const Rect2i & p_rect , const Color & p_color , const Color & p_icon_color , int p_ol_size , const Color & p_ol_color ) {
2018-01-06 19:48:54 +01:00
ERR_FAIL_COND ( cache . font . is_null ( ) ) ;
2017-03-05 16:44:50 +01:00
Rect2i rect = p_rect ;
2020-09-03 13:22:16 +02:00
Size2 ts = p_cell . text_buf - > get_size ( ) ;
bool rtl = is_layout_rtl ( ) ;
2017-06-25 22:30:28 +02:00
int w = 0 ;
if ( ! p_cell . icon . is_null ( ) ) {
Size2i bmsize = p_cell . get_icon_size ( ) ;
if ( p_cell . icon_max_w > 0 & & bmsize . width > p_cell . icon_max_w ) {
bmsize . width = p_cell . icon_max_w ;
}
w + = bmsize . width + cache . hseparation ;
2020-09-03 13:22:16 +02:00
if ( rect . size . width > 0 & & ( w + ts . width ) > rect . size . width ) {
ts . width = rect . size . width - w ;
}
2017-06-25 22:30:28 +02:00
}
2020-09-03 13:22:16 +02:00
w + = ts . width ;
2017-06-25 22:30:28 +02:00
2021-11-25 03:58:47 +01:00
switch ( p_cell . text_alignment ) {
case HORIZONTAL_ALIGNMENT_FILL :
case HORIZONTAL_ALIGNMENT_LEFT : {
2020-09-03 13:22:16 +02:00
if ( rtl ) {
rect . position . x + = MAX ( 0 , ( rect . size . width - w ) ) ;
}
2021-11-25 03:58:47 +01:00
} break ;
case HORIZONTAL_ALIGNMENT_CENTER :
2017-12-28 11:27:57 +01:00
rect . position . x + = MAX ( 0 , ( rect . size . width - w ) / 2 ) ;
2020-09-03 13:22:16 +02:00
break ;
2021-11-25 03:58:47 +01:00
case HORIZONTAL_ALIGNMENT_RIGHT :
2020-09-03 13:22:16 +02:00
if ( ! rtl ) {
rect . position . x + = MAX ( 0 , ( rect . size . width - w ) ) ;
}
break ;
2017-06-25 22:30:28 +02:00
}
2014-02-10 02:10:30 +01:00
RID ci = get_canvas_item ( ) ;
2020-09-03 13:22:16 +02:00
if ( rtl ) {
Point2 draw_pos = rect . position ;
draw_pos . y + = Math : : floor ( ( rect . size . y - p_cell . text_buf - > get_size ( ) . y ) / 2.0 ) ;
p_cell . text_buf - > set_width ( MAX ( 0 , rect . size . width ) ) ;
2020-12-25 22:45:28 +01:00
if ( p_ol_size > 0 & & p_ol_color . a > 0 ) {
p_cell . text_buf - > draw_outline ( ci , draw_pos , p_ol_size , p_ol_color ) ;
}
2020-09-03 13:22:16 +02:00
p_cell . text_buf - > draw ( ci , draw_pos , p_color ) ;
rect . position . x + = ts . width + cache . hseparation ;
rect . size . x - = ts . width + cache . hseparation ;
}
2014-02-10 02:10:30 +01:00
if ( ! p_cell . icon . is_null ( ) ) {
Size2i bmsize = p_cell . get_icon_size ( ) ;
2017-03-05 16:44:50 +01:00
if ( p_cell . icon_max_w > 0 & & bmsize . width > p_cell . icon_max_w ) {
2014-02-10 02:10:30 +01:00
bmsize . height = bmsize . height * p_cell . icon_max_w / bmsize . width ;
2017-03-05 16:44:50 +01:00
bmsize . width = p_cell . icon_max_w ;
2014-02-10 02:10:30 +01:00
}
2017-07-19 22:00:46 +02:00
p_cell . draw_icon ( ci , rect . position + Size2i ( 0 , Math : : floor ( ( real_t ) ( rect . size . y - bmsize . y ) / 2 ) ) , bmsize , p_icon_color ) ;
2017-06-04 00:25:13 +02:00
rect . position . x + = bmsize . x + cache . hseparation ;
2017-03-05 16:44:50 +01:00
rect . size . x - = bmsize . x + cache . hseparation ;
2014-02-10 02:10:30 +01:00
}
2020-09-03 13:22:16 +02:00
if ( ! rtl ) {
Point2 draw_pos = rect . position ;
draw_pos . y + = Math : : floor ( ( rect . size . y - p_cell . text_buf - > get_size ( ) . y ) / 2.0 ) ;
p_cell . text_buf - > set_width ( MAX ( 0 , rect . size . width ) ) ;
2020-12-25 22:45:28 +01:00
if ( p_ol_size > 0 & & p_ol_color . a > 0 ) {
p_cell . text_buf - > draw_outline ( ci , draw_pos , p_ol_size , p_ol_color ) ;
}
2020-09-03 13:22:16 +02:00
p_cell . text_buf - > draw ( ci , draw_pos , p_color ) ;
}
}
void Tree : : update_column ( int p_col ) {
columns . write [ p_col ] . text_buf - > clear ( ) ;
if ( columns [ p_col ] . text_direction = = Control : : TEXT_DIRECTION_INHERITED ) {
columns . write [ p_col ] . text_buf - > set_direction ( is_layout_rtl ( ) ? TextServer : : DIRECTION_RTL : TextServer : : DIRECTION_LTR ) ;
} else {
columns . write [ p_col ] . text_buf - > set_direction ( ( TextServer : : Direction ) columns [ p_col ] . text_direction ) ;
}
2021-05-27 17:32:30 +02:00
2021-12-09 10:42:46 +01:00
columns . write [ p_col ] . text_buf - > add_string ( columns [ p_col ] . title , cache . font , cache . font_size , columns [ p_col ] . opentype_features , ! columns [ p_col ] . language . is_empty ( ) ? columns [ p_col ] . language : TranslationServer : : get_singleton ( ) - > get_tool_locale ( ) ) ;
2020-09-03 13:22:16 +02:00
}
void Tree : : update_item_cell ( TreeItem * p_item , int p_col ) {
String valtext ;
p_item - > cells . write [ p_col ] . text_buf - > clear ( ) ;
if ( p_item - > cells [ p_col ] . mode = = TreeItem : : CELL_MODE_RANGE ) {
2021-12-09 10:42:46 +01:00
if ( ! p_item - > cells [ p_col ] . text . is_empty ( ) ) {
2020-09-03 13:22:16 +02:00
if ( ! p_item - > cells [ p_col ] . editable ) {
return ;
}
int option = ( int ) p_item - > cells [ p_col ] . val ;
valtext = RTR ( " (Other) " ) ;
Vector < String > strings = p_item - > cells [ p_col ] . text . split ( " , " ) ;
for ( int j = 0 ; j < strings . size ( ) ; j + + ) {
int value = j ;
2020-12-15 13:04:21 +01:00
if ( ! strings [ j ] . get_slicec ( ' : ' , 1 ) . is_empty ( ) ) {
2020-09-03 13:22:16 +02:00
value = strings [ j ] . get_slicec ( ' : ' , 1 ) . to_int ( ) ;
}
if ( option = = value ) {
valtext = strings [ j ] . get_slicec ( ' : ' , 0 ) ;
break ;
}
}
} else {
valtext = String : : num ( p_item - > cells [ p_col ] . val , Math : : range_step_decimals ( p_item - > cells [ p_col ] . step ) ) ;
}
} else {
valtext = p_item - > cells [ p_col ] . text ;
}
2021-12-09 10:42:46 +01:00
if ( ! p_item - > cells [ p_col ] . suffix . is_empty ( ) ) {
2020-09-03 13:22:16 +02:00
valtext + = " " + p_item - > cells [ p_col ] . suffix ;
}
if ( p_item - > cells [ p_col ] . text_direction = = Control : : TEXT_DIRECTION_INHERITED ) {
p_item - > cells . write [ p_col ] . text_buf - > set_direction ( is_layout_rtl ( ) ? TextServer : : DIRECTION_RTL : TextServer : : DIRECTION_LTR ) ;
} else {
p_item - > cells . write [ p_col ] . text_buf - > set_direction ( ( TextServer : : Direction ) p_item - > cells [ p_col ] . text_direction ) ;
}
2021-05-27 17:32:30 +02:00
Ref < Font > font ;
if ( p_item - > cells [ p_col ] . custom_font . is_valid ( ) ) {
font = p_item - > cells [ p_col ] . custom_font ;
} else {
font = cache . font ;
}
2020-12-27 14:30:33 +01:00
int font_size ;
if ( p_item - > cells [ p_col ] . custom_font_size > 0 ) {
font_size = p_item - > cells [ p_col ] . custom_font_size ;
} else {
font_size = cache . font_size ;
}
2021-12-09 10:42:46 +01:00
p_item - > cells . write [ p_col ] . text_buf - > add_string ( valtext , font , font_size , p_item - > cells [ p_col ] . opentype_features , ! p_item - > cells [ p_col ] . language . is_empty ( ) ? p_item - > cells [ p_col ] . language : TranslationServer : : get_singleton ( ) - > get_tool_locale ( ) ) ;
2020-09-03 13:22:16 +02:00
TS - > shaped_text_set_bidi_override ( p_item - > cells [ p_col ] . text_buf - > get_rid ( ) , structured_text_parser ( p_item - > cells [ p_col ] . st_parser , p_item - > cells [ p_col ] . st_args , valtext ) ) ;
p_item - > cells . write [ p_col ] . dirty = false ;
}
void Tree : : update_item_cache ( TreeItem * p_item ) {
for ( int i = 0 ; i < p_item - > cells . size ( ) ; i + + ) {
update_item_cell ( p_item , i ) ;
}
2021-03-07 21:07:30 +01:00
TreeItem * c = p_item - > first_child ;
2020-09-03 13:22:16 +02:00
while ( c ) {
update_item_cache ( c ) ;
c = c - > next ;
}
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
int Tree : : draw_item ( const Point2i & p_pos , const Point2 & p_draw_ofs , const Size2 & p_draw_size , TreeItem * p_item ) {
2020-05-14 16:41:43 +02:00
if ( p_pos . y - cache . offset . y > ( p_draw_size . height ) ) {
2014-02-10 02:10:30 +01:00
return - 1 ; //draw no more!
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
RID ci = get_canvas_item ( ) ;
2017-03-05 16:44:50 +01:00
int htotal = 0 ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
int label_h = compute_item_height ( p_item ) ;
2021-07-04 05:13:28 +02:00
bool rtl = cache . rtl ;
2014-02-10 02:10:30 +01:00
/* Calculate height of the label part */
2017-03-05 16:44:50 +01:00
label_h + = cache . vseparation ;
2014-02-10 02:10:30 +01:00
/* Draw label, if height fits */
2017-03-05 16:44:50 +01:00
bool skip = ( p_item = = root & & hide_root ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
if ( ! skip & & ( p_pos . y + label_h - cache . offset . y ) > 0 ) {
2014-02-10 02:10:30 +01:00
//draw separation.
2017-01-14 12:26:56 +01:00
//if (p_item->get_parent()!=root || !hide_root)
2014-02-10 02:10:30 +01:00
2018-01-06 19:48:54 +01:00
ERR_FAIL_COND_V ( cache . font . is_null ( ) , - 1 ) ;
2014-02-10 02:10:30 +01:00
2017-06-25 22:30:28 +02:00
int ofs = p_pos . x + ( ( p_item - > disable_folding | | hide_folding ) ? cache . hseparation : cache . item_margin ) ;
2019-02-12 21:10:08 +01:00
int skip2 = 0 ;
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < columns . size ( ) ; i + + ) {
2019-02-12 21:10:08 +01:00
if ( skip2 ) {
skip2 - - ;
2017-06-25 22:30:28 +02:00
continue ;
}
2014-02-10 02:10:30 +01:00
int w = get_column_width ( i ) ;
2017-03-05 16:44:50 +01:00
if ( i = = 0 ) {
w - = ofs ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
if ( w < = 0 ) {
ofs = get_column_width ( 0 ) ;
2014-02-10 02:10:30 +01:00
continue ;
}
} else {
2017-03-05 16:44:50 +01:00
ofs + = cache . hseparation ;
w - = cache . hseparation ;
2014-02-10 02:10:30 +01:00
}
2017-06-25 22:30:28 +02:00
if ( p_item - > cells [ i ] . expand_right ) {
int plus = 1 ;
2021-12-09 10:42:46 +01:00
while ( i + plus < columns . size ( ) & & ! p_item - > cells [ i + plus ] . editable & & p_item - > cells [ i + plus ] . mode = = TreeItem : : CELL_MODE_STRING & & p_item - > cells [ i + plus ] . text . is_empty ( ) & & p_item - > cells [ i + plus ] . icon . is_null ( ) ) {
2017-06-25 22:30:28 +02:00
w + = get_column_width ( i + plus ) ;
plus + + ;
2019-02-12 21:10:08 +01:00
skip2 + + ;
2017-06-25 22:30:28 +02:00
}
}
2021-07-04 05:13:28 +02:00
if ( ! rtl & & p_item - > cells [ i ] . buttons . size ( ) ) {
int button_w = 0 ;
for ( int j = p_item - > cells [ i ] . buttons . size ( ) - 1 ; j > = 0 ; j - - ) {
Ref < Texture2D > b = p_item - > cells [ i ] . buttons [ j ] . texture ;
button_w + = b - > get_size ( ) . width + cache . button_pressed - > get_minimum_size ( ) . width + cache . button_margin ;
}
int total_ofs = ofs - cache . offset . x ;
if ( total_ofs + w > p_draw_size . width ) {
w = MAX ( button_w , p_draw_size . width - total_ofs ) ;
}
}
2017-03-05 16:44:50 +01:00
int bw = 0 ;
for ( int j = p_item - > cells [ i ] . buttons . size ( ) - 1 ; j > = 0 ; j - - ) {
2019-06-11 20:43:37 +02:00
Ref < Texture2D > b = p_item - > cells [ i ] . buttons [ j ] . texture ;
2014-02-10 02:10:30 +01:00
Size2 s = b - > get_size ( ) + cache . button_pressed - > get_minimum_size ( ) ;
2020-05-14 16:41:43 +02:00
if ( s . height < label_h ) {
2019-06-23 18:06:47 +02:00
s . height = label_h ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
Point2i o = Point2i ( ofs + w - s . width , p_pos . y ) - cache . offset + p_draw_ofs ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
if ( cache . click_type = = Cache : : CLICK_BUTTON & & cache . click_item = = p_item & & cache . click_column = = i & & cache . click_index = = j & & ! p_item - > cells [ i ] . buttons [ j ] . disabled ) {
2014-02-10 02:10:30 +01:00
//being pressed
2020-09-03 13:22:16 +02:00
Point2 od = o ;
if ( rtl ) {
od . x = get_size ( ) . width - od . x - s . x ;
}
cache . button_pressed - > draw ( get_canvas_item ( ) , Rect2 ( od , s ) ) ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
o . y + = ( label_h - s . height ) / 2 ;
o + = cache . button_pressed - > get_offset ( ) ;
2016-02-03 00:44:42 +01:00
2020-09-03 13:22:16 +02:00
if ( rtl ) {
o . x = get_size ( ) . width - o . x - b - > get_width ( ) ;
}
2017-03-05 16:44:50 +01:00
b - > draw ( ci , o , p_item - > cells [ i ] . buttons [ j ] . disabled ? Color ( 1 , 1 , 1 , 0.5 ) : p_item - > cells [ i ] . buttons [ j ] . color ) ;
w - = s . width + cache . button_margin ;
bw + = s . width + cache . button_margin ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
Rect2i item_rect = Rect2i ( Point2i ( ofs , p_pos . y ) - cache . offset + p_draw_ofs , Size2i ( w , label_h ) ) ;
Rect2i cell_rect = item_rect ;
if ( i ! = 0 ) {
2017-06-04 00:25:13 +02:00
cell_rect . position . x - = cache . hseparation ;
2017-03-05 16:44:50 +01:00
cell_rect . size . x + = cache . hseparation ;
2014-02-10 02:10:30 +01:00
}
2018-11-19 02:00:31 +01:00
if ( cache . draw_guides ) {
2020-09-03 13:22:16 +02:00
Rect2 r = cell_rect ;
if ( rtl ) {
r . position . x = get_size ( ) . width - r . position . x - r . size . x ;
}
RenderingServer : : get_singleton ( ) - > canvas_item_add_line ( ci , Point2i ( r . position . x , r . position . y + r . size . height ) , r . position + r . size , cache . guide_color , 1 ) ;
2018-11-19 02:00:31 +01:00
}
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
if ( i = = 0 ) {
if ( p_item - > cells [ 0 ] . selected & & select_mode = = SELECT_ROW ) {
2020-12-22 17:24:29 +01:00
Rect2i row_rect = Rect2i ( Point2i ( cache . bg - > get_margin ( SIDE_LEFT ) , item_rect . position . y ) , Size2i ( get_size ( ) . width - cache . bg - > get_minimum_size ( ) . width , item_rect . size . y ) ) ;
2014-02-10 02:10:30 +01:00
//Rect2 r = Rect2i(row_rect.pos,row_rect.size);
2020-12-22 17:24:29 +01:00
//r.grow(cache.selected->get_margin(SIDE_LEFT));
2020-09-03 13:22:16 +02:00
if ( rtl ) {
row_rect . position . x = get_size ( ) . width - row_rect . position . x - row_rect . size . x ;
}
2020-05-14 16:41:43 +02:00
if ( has_focus ( ) ) {
2017-03-05 16:44:50 +01:00
cache . selected_focus - > draw ( ci , row_rect ) ;
2020-05-14 16:41:43 +02:00
} else {
2017-03-05 16:44:50 +01:00
cache . selected - > draw ( ci , row_rect ) ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
}
}
2020-02-03 23:10:24 +01:00
if ( ( select_mode = = SELECT_ROW & & selected_item = = p_item ) | | p_item - > cells [ i ] . selected | | ! p_item - > has_meta ( " __focus_rect " ) ) {
2021-09-25 11:01:45 +02:00
Rect2i r = cell_rect ;
2019-08-11 15:54:55 +02:00
2019-01-16 12:44:34 +01:00
p_item - > set_meta ( " __focus_rect " , Rect2 ( r . position , r . size ) ) ;
2019-08-11 15:54:55 +02:00
2020-09-03 13:22:16 +02:00
if ( rtl ) {
r . position . x = get_size ( ) . width - r . position . x - r . size . x ;
}
2019-08-11 15:54:55 +02:00
if ( p_item - > cells [ i ] . selected ) {
if ( has_focus ( ) ) {
cache . selected_focus - > draw ( ci , r ) ;
} else {
cache . selected - > draw ( ci , r ) ;
}
2016-08-20 18:00:25 +02:00
}
2014-02-10 02:10:30 +01:00
}
if ( p_item - > cells [ i ] . custom_bg_color ) {
2017-03-05 16:44:50 +01:00
Rect2 r = cell_rect ;
2017-06-26 02:12:36 +02:00
if ( i = = 0 ) {
r . position . x = p_draw_ofs . x ;
r . size . x = w + ofs ;
} else {
r . position . x - = cache . hseparation ;
r . size . x + = cache . hseparation ;
}
2020-09-03 13:22:16 +02:00
if ( rtl ) {
r . position . x = get_size ( ) . width - r . position . x - r . size . x ;
}
2016-05-11 16:46:08 +02:00
if ( p_item - > cells [ i ] . custom_bg_outline ) {
2020-03-27 19:21:27 +01:00
RenderingServer : : get_singleton ( ) - > canvas_item_add_rect ( ci , Rect2 ( r . position . x , r . position . y , r . size . x , 1 ) , p_item - > cells [ i ] . bg_color ) ;
RenderingServer : : get_singleton ( ) - > canvas_item_add_rect ( ci , Rect2 ( r . position . x , r . position . y + r . size . y - 1 , r . size . x , 1 ) , p_item - > cells [ i ] . bg_color ) ;
RenderingServer : : get_singleton ( ) - > canvas_item_add_rect ( ci , Rect2 ( r . position . x , r . position . y , 1 , r . size . y ) , p_item - > cells [ i ] . bg_color ) ;
RenderingServer : : get_singleton ( ) - > canvas_item_add_rect ( ci , Rect2 ( r . position . x + r . size . x - 1 , r . position . y , 1 , r . size . y ) , p_item - > cells [ i ] . bg_color ) ;
2016-05-11 16:46:08 +02:00
} else {
2020-03-27 19:21:27 +01:00
RenderingServer : : get_singleton ( ) - > canvas_item_add_rect ( ci , r , p_item - > cells [ i ] . bg_color ) ;
2016-05-11 16:46:08 +02:00
}
}
2021-08-25 12:03:16 +02:00
if ( drop_mode_flags & & drop_mode_over ) {
2017-03-05 16:44:50 +01:00
Rect2 r = cell_rect ;
2020-09-03 13:22:16 +02:00
if ( rtl ) {
r . position . x = get_size ( ) . width - r . position . x - r . size . x ;
}
2021-08-25 12:03:16 +02:00
if ( drop_mode_over = = p_item ) {
if ( drop_mode_section = = 0 | | drop_mode_section = = - 1 ) {
// Line above.
RenderingServer : : get_singleton ( ) - > canvas_item_add_rect ( ci , Rect2 ( r . position . x , r . position . y , r . size . x , 1 ) , cache . drop_position_color ) ;
}
if ( drop_mode_section = = 0 ) {
// Side lines.
RenderingServer : : get_singleton ( ) - > canvas_item_add_rect ( ci , Rect2 ( r . position . x , r . position . y , 1 , r . size . y ) , cache . drop_position_color ) ;
RenderingServer : : get_singleton ( ) - > canvas_item_add_rect ( ci , Rect2 ( r . position . x + r . size . x - 1 , r . position . y , 1 , r . size . y ) , cache . drop_position_color ) ;
}
if ( drop_mode_section = = 0 | | ( drop_mode_section = = 1 & & ( ! p_item - > get_first_child ( ) | | p_item - > is_collapsed ( ) ) ) ) {
// Line below.
RenderingServer : : get_singleton ( ) - > canvas_item_add_rect ( ci , Rect2 ( r . position . x , r . position . y + r . size . y , r . size . x , 1 ) , cache . drop_position_color ) ;
}
} else if ( drop_mode_over = = p_item - > get_parent ( ) ) {
if ( drop_mode_section = = 1 & & ! p_item - > get_prev ( ) /* && !drop_mode_over->is_collapsed() */ ) { // The drop_mode_over shouldn't ever be collapsed in here, otherwise we would be drawing a child of a collapsed item.
// Line above.
RenderingServer : : get_singleton ( ) - > canvas_item_add_rect ( ci , Rect2 ( r . position . x , r . position . y , r . size . x , 1 ) , cache . drop_position_color ) ;
}
2016-05-11 16:46:08 +02:00
}
2014-02-10 02:10:30 +01:00
}
2020-12-08 14:11:45 +01:00
Color col = p_item - > cells [ i ] . custom_color ? p_item - > cells [ i ] . color : get_theme_color ( p_item - > cells [ i ] . selected ? " font_selected_color " : " font_color " ) ;
2021-07-04 05:13:28 +02:00
Color font_outline_color = cache . font_outline_color ;
int outline_size = cache . font_outline_size ;
2017-07-19 22:00:46 +02:00
Color icon_col = p_item - > cells [ i ] . icon_color ;
2015-08-31 00:37:23 +02:00
2020-09-03 13:22:16 +02:00
if ( p_item - > cells [ i ] . dirty ) {
const_cast < Tree * > ( this ) - > update_item_cell ( p_item , i ) ;
}
if ( rtl ) {
item_rect . position . x = get_size ( ) . width - item_rect . position . x - item_rect . size . x ;
}
2017-06-04 00:25:13 +02:00
Point2i text_pos = item_rect . position ;
2020-09-03 13:22:16 +02:00
text_pos . y + = Math : : floor ( ( item_rect . size . y - p_item - > cells [ i ] . text_buf - > get_size ( ) . y ) / 2 ) ;
int text_width = p_item - > cells [ i ] . text_buf - > get_size ( ) . x ;
2014-02-10 02:10:30 +01:00
switch ( p_item - > cells [ i ] . mode ) {
case TreeItem : : CELL_MODE_STRING : {
2020-12-25 22:45:28 +01:00
draw_item_rect ( p_item - > cells . write [ i ] , item_rect , col , icon_col , outline_size , font_outline_color ) ;
2014-02-10 02:10:30 +01:00
} break ;
case TreeItem : : CELL_MODE_CHECK : {
2019-06-11 20:43:37 +02:00
Ref < Texture2D > checked = cache . checked ;
Ref < Texture2D > unchecked = cache . unchecked ;
2021-07-22 22:34:54 +02:00
Ref < Texture2D > indeterminate = cache . indeterminate ;
2017-06-04 00:25:13 +02:00
Point2i check_ofs = item_rect . position ;
2017-03-05 16:44:50 +01:00
check_ofs . y + = Math : : floor ( ( real_t ) ( item_rect . size . y - checked - > get_height ( ) ) / 2 ) ;
2014-02-10 02:10:30 +01:00
2021-07-22 22:34:54 +02:00
if ( p_item - > cells [ i ] . indeterminate ) {
indeterminate - > draw ( ci , check_ofs ) ;
} else if ( p_item - > cells [ i ] . checked ) {
2019-08-24 17:13:48 +02:00
checked - > draw ( ci , check_ofs ) ;
2014-02-10 02:10:30 +01:00
} else {
2019-08-24 17:13:48 +02:00
unchecked - > draw ( ci , check_ofs ) ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
int check_w = checked - > get_width ( ) + cache . hseparation ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
text_pos . x + = check_w ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
item_rect . size . x - = check_w ;
2017-06-04 00:25:13 +02:00
item_rect . position . x + = check_w ;
2014-02-10 02:10:30 +01:00
2020-12-25 22:45:28 +01:00
draw_item_rect ( p_item - > cells . write [ i ] , item_rect , col , icon_col , outline_size , font_outline_color ) ;
2014-02-10 02:10:30 +01:00
} break ;
2018-09-22 22:31:56 +02:00
case TreeItem : : CELL_MODE_RANGE : {
2021-12-09 10:42:46 +01:00
if ( ! p_item - > cells [ i ] . text . is_empty ( ) ) {
2020-05-14 16:41:43 +02:00
if ( ! p_item - > cells [ i ] . editable ) {
2014-02-10 02:10:30 +01:00
break ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2019-06-11 20:43:37 +02:00
Ref < Texture2D > downarrow = cache . select_arrow ;
2020-09-03 13:22:16 +02:00
int cell_width = item_rect . size . x - downarrow - > get_width ( ) ;
2014-02-10 02:10:30 +01:00
2020-09-03 13:22:16 +02:00
p_item - > cells . write [ i ] . text_buf - > set_width ( cell_width ) ;
if ( rtl ) {
2020-12-25 22:45:28 +01:00
if ( outline_size > 0 & & font_outline_color . a > 0 ) {
p_item - > cells [ i ] . text_buf - > draw_outline ( ci , text_pos + Vector2 ( cell_width - text_width , 0 ) , outline_size , font_outline_color ) ;
}
2020-09-03 13:22:16 +02:00
p_item - > cells [ i ] . text_buf - > draw ( ci , text_pos + Vector2 ( cell_width - text_width , 0 ) , col ) ;
} else {
2020-12-25 22:45:28 +01:00
if ( outline_size > 0 & & font_outline_color . a > 0 ) {
p_item - > cells [ i ] . text_buf - > draw_outline ( ci , text_pos , outline_size , font_outline_color ) ;
}
2020-09-03 13:22:16 +02:00
p_item - > cells [ i ] . text_buf - > draw ( ci , text_pos , col ) ;
}
2014-02-10 02:10:30 +01:00
2017-06-04 00:25:13 +02:00
Point2i arrow_pos = item_rect . position ;
2017-03-05 16:44:50 +01:00
arrow_pos . x + = item_rect . size . x - downarrow - > get_width ( ) ;
arrow_pos . y + = Math : : floor ( ( ( item_rect . size . y - downarrow - > get_height ( ) ) ) / 2.0 ) ;
2014-02-10 02:10:30 +01:00
2019-08-24 17:13:48 +02:00
downarrow - > draw ( ci , arrow_pos ) ;
2014-02-10 02:10:30 +01:00
} else {
2019-06-11 20:43:37 +02:00
Ref < Texture2D > updown = cache . updown ;
2015-08-31 00:37:23 +02:00
2020-09-03 13:22:16 +02:00
int cell_width = item_rect . size . x - updown - > get_width ( ) ;
2016-08-31 04:44:14 +02:00
2020-09-03 13:22:16 +02:00
if ( rtl ) {
2020-12-25 22:45:28 +01:00
if ( outline_size > 0 & & font_outline_color . a > 0 ) {
p_item - > cells [ i ] . text_buf - > draw_outline ( ci , text_pos + Vector2 ( cell_width - text_width , 0 ) , outline_size , font_outline_color ) ;
}
2020-09-03 13:22:16 +02:00
p_item - > cells [ i ] . text_buf - > draw ( ci , text_pos + Vector2 ( cell_width - text_width , 0 ) , col ) ;
} else {
2020-12-25 22:45:28 +01:00
if ( outline_size > 0 & & font_outline_color . a > 0 ) {
p_item - > cells [ i ] . text_buf - > draw_outline ( ci , text_pos , outline_size , font_outline_color ) ;
}
2020-09-03 13:22:16 +02:00
p_item - > cells [ i ] . text_buf - > draw ( ci , text_pos , col ) ;
2020-05-14 16:41:43 +02:00
}
2016-08-31 04:44:14 +02:00
2020-05-14 16:41:43 +02:00
if ( ! p_item - > cells [ i ] . editable ) {
2014-02-10 02:10:30 +01:00
break ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2017-06-04 00:25:13 +02:00
Point2i updown_pos = item_rect . position ;
2017-03-05 16:44:50 +01:00
updown_pos . x + = item_rect . size . x - updown - > get_width ( ) ;
updown_pos . y + = Math : : floor ( ( ( item_rect . size . y - updown - > get_height ( ) ) ) / 2.0 ) ;
2014-02-10 02:10:30 +01:00
2019-08-24 17:13:48 +02:00
updown - > draw ( ci , updown_pos ) ;
2014-02-10 02:10:30 +01:00
}
} break ;
case TreeItem : : CELL_MODE_ICON : {
2020-05-14 16:41:43 +02:00
if ( p_item - > cells [ i ] . icon . is_null ( ) ) {
2014-02-10 02:10:30 +01:00
break ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
Size2i icon_size = p_item - > cells [ i ] . get_icon_size ( ) ;
2017-03-05 16:44:50 +01:00
if ( p_item - > cells [ i ] . icon_max_w > 0 & & icon_size . width > p_item - > cells [ i ] . icon_max_w ) {
2014-02-10 02:10:30 +01:00
icon_size . height = icon_size . height * p_item - > cells [ i ] . icon_max_w / icon_size . width ;
2017-03-05 16:44:50 +01:00
icon_size . width = p_item - > cells [ i ] . icon_max_w ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
Point2i icon_ofs = ( item_rect . size - icon_size ) / 2 ;
2017-06-04 00:25:13 +02:00
icon_ofs + = item_rect . position ;
2014-02-10 02:10:30 +01:00
2017-07-19 22:00:46 +02:00
draw_texture_rect ( p_item - > cells [ i ] . icon , Rect2 ( icon_ofs , icon_size ) , false , icon_col ) ;
2014-02-10 02:10:30 +01:00
} break ;
case TreeItem : : CELL_MODE_CUSTOM : {
2020-02-12 18:24:06 +01:00
if ( p_item - > cells [ i ] . custom_draw_obj . is_valid ( ) ) {
2017-03-05 16:44:50 +01:00
Object * cdo = ObjectDB : : get_instance ( p_item - > cells [ i ] . custom_draw_obj ) ;
2020-05-14 16:41:43 +02:00
if ( cdo ) {
2017-03-05 16:44:50 +01:00
cdo - > call ( p_item - > cells [ i ] . custom_draw_callback , p_item , Rect2 ( item_rect ) ) ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
}
if ( ! p_item - > cells [ i ] . editable ) {
2020-12-25 22:45:28 +01:00
draw_item_rect ( p_item - > cells . write [ i ] , item_rect , col , icon_col , outline_size , font_outline_color ) ;
2014-02-10 02:10:30 +01:00
break ;
}
2019-06-11 20:43:37 +02:00
Ref < Texture2D > downarrow = cache . select_arrow ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
Rect2i ir = item_rect ;
2015-08-31 00:37:23 +02:00
2017-06-04 00:25:13 +02:00
Point2i arrow_pos = item_rect . position ;
2017-03-05 16:44:50 +01:00
arrow_pos . x + = item_rect . size . x - downarrow - > get_width ( ) ;
arrow_pos . y + = Math : : floor ( ( ( item_rect . size . y - downarrow - > get_height ( ) ) ) / 2.0 ) ;
2017-06-05 01:35:08 +02:00
ir . size . width - = downarrow - > get_width ( ) ;
if ( p_item - > cells [ i ] . custom_button ) {
if ( cache . hover_item = = p_item & & cache . hover_cell = = i ) {
2021-08-13 23:31:57 +02:00
if ( Input : : get_singleton ( ) - > is_mouse_button_pressed ( MouseButton : : LEFT ) ) {
2017-06-05 01:35:08 +02:00
draw_style_box ( cache . custom_button_pressed , ir ) ;
} else {
draw_style_box ( cache . custom_button_hover , ir ) ;
col = cache . custom_button_font_highlight ;
}
} else {
draw_style_box ( cache . custom_button , ir ) ;
}
ir . size - = cache . custom_button - > get_minimum_size ( ) ;
2017-06-05 16:15:01 +02:00
ir . position + = cache . custom_button - > get_offset ( ) ;
2017-06-05 01:35:08 +02:00
}
2020-12-25 22:45:28 +01:00
draw_item_rect ( p_item - > cells . write [ i ] , ir , col , icon_col , outline_size , font_outline_color ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
downarrow - > draw ( ci , arrow_pos ) ;
2014-02-10 02:10:30 +01:00
} break ;
}
2017-03-05 16:44:50 +01:00
if ( i = = 0 ) {
ofs = get_column_width ( 0 ) ;
2014-02-10 02:10:30 +01:00
} else {
2017-03-05 16:44:50 +01:00
ofs + = w + bw ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
if ( select_mode = = SELECT_MULTI & & selected_item = = p_item & & selected_col = = i ) {
2020-09-03 13:22:16 +02:00
if ( is_layout_rtl ( ) ) {
cell_rect . position . x = get_size ( ) . width - cell_rect . position . x - cell_rect . size . x ;
}
2020-05-14 16:41:43 +02:00
if ( has_focus ( ) ) {
2017-03-05 16:44:50 +01:00
cache . cursor - > draw ( ci , cell_rect ) ;
2020-05-14 16:41:43 +02:00
} else {
2017-03-05 16:44:50 +01:00
cache . cursor_unfocus - > draw ( ci , cell_rect ) ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
}
}
2021-03-07 21:07:30 +01:00
if ( ! p_item - > disable_folding & & ! hide_folding & & p_item - > first_child ) { //has children, draw the guide box
2017-06-26 02:12:36 +02:00
2019-06-11 20:43:37 +02:00
Ref < Texture2D > arrow ;
2017-06-26 02:12:36 +02:00
if ( p_item - > collapsed ) {
arrow = cache . arrow_collapsed ;
} else {
arrow = cache . arrow ;
}
2021-09-25 01:01:14 +02:00
Point2 apos = p_pos + Point2i ( 0 , ( label_h - arrow - > get_height ( ) ) / 2 ) - cache . offset + p_draw_ofs ;
apos . x + = cache . item_margin - arrow - > get_width ( ) ;
2020-09-03 13:22:16 +02:00
if ( rtl ) {
apos . x = get_size ( ) . width - apos . x - arrow - > get_width ( ) ;
}
arrow - > draw ( ci , apos ) ;
2017-06-26 02:12:36 +02:00
}
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
Point2 children_pos = p_pos ;
2014-02-10 02:10:30 +01:00
if ( ! skip ) {
2017-03-05 16:44:50 +01:00
children_pos . x + = cache . item_margin ;
htotal + = label_h ;
children_pos . y + = htotal ;
2014-02-10 02:10:30 +01:00
}
2018-01-18 21:37:17 +01:00
if ( ! p_item - > collapsed ) { /* if not collapsed, check the children */
2014-02-10 02:10:30 +01:00
2021-03-07 21:07:30 +01:00
TreeItem * c = p_item - > first_child ;
2014-02-10 02:10:30 +01:00
2021-05-02 17:34:29 +02:00
int base_ofs = children_pos . y - cache . offset . y + p_draw_ofs . y ;
int prev_ofs = base_ofs ;
int prev_hl_ofs = base_ofs ;
2019-03-06 16:10:36 +01:00
2014-02-10 02:10:30 +01:00
while ( c ) {
2021-06-21 15:46:43 +02:00
if ( htotal > = 0 ) {
int child_h = draw_item ( children_pos , p_draw_ofs , p_draw_size , c ) ;
2019-03-06 16:10:36 +01:00
2021-06-21 15:46:43 +02:00
// Draw relationship lines.
if ( cache . draw_relationship_lines > 0 & & ( ! hide_root | | c - > parent ! = root ) ) {
int root_ofs = children_pos . x + ( ( p_item - > disable_folding | | hide_folding ) ? cache . hseparation : cache . item_margin ) ;
int parent_ofs = p_pos . x + cache . item_margin ;
Point2i root_pos = Point2i ( root_ofs , children_pos . y + label_h / 2 ) - cache . offset + p_draw_ofs ;
2016-06-15 19:10:19 +02:00
2021-06-21 15:46:43 +02:00
if ( c - > get_first_child ( ) ! = nullptr ) {
root_pos - = Point2i ( cache . arrow - > get_width ( ) , 0 ) ;
}
2021-10-02 22:07:42 +02:00
float line_width = cache . relationship_line_width * Math : : round ( cache . base_scale ) ;
float parent_line_width = cache . parent_hl_line_width * Math : : round ( cache . base_scale ) ;
float children_line_width = cache . children_hl_line_width * Math : : round ( cache . base_scale ) ;
2017-12-15 18:40:45 +01:00
2021-06-21 15:46:43 +02:00
Point2i parent_pos = Point2i ( parent_ofs - cache . arrow - > get_width ( ) / 2 , p_pos . y + label_h / 2 + cache . arrow - > get_height ( ) / 2 ) - cache . offset + p_draw_ofs ;
2018-01-04 10:03:46 +01:00
2021-06-21 15:46:43 +02:00
int more_prev_ofs = 0 ;
2021-05-02 17:34:29 +02:00
2021-06-21 15:46:43 +02:00
if ( root_pos . y + line_width > = 0 ) {
if ( rtl ) {
root_pos . x = get_size ( ) . width - root_pos . x ;
parent_pos . x = get_size ( ) . width - parent_pos . x ;
}
2021-05-02 17:34:29 +02:00
2021-06-21 15:46:43 +02:00
// Order of parts on this bend: the horizontal line first, then the vertical line.
if ( _is_branch_selected ( c ) ) {
// If this item or one of its children is selected, we draw the line using parent highlight style.
RenderingServer : : get_singleton ( ) - > canvas_item_add_line ( ci , root_pos , Point2i ( parent_pos . x + Math : : floor ( parent_line_width / 2 ) , root_pos . y ) , cache . parent_hl_line_color , parent_line_width ) ;
2021-05-25 23:44:04 +02:00
RenderingServer : : get_singleton ( ) - > canvas_item_add_line ( ci , Point2i ( parent_pos . x , root_pos . y + Math : : floor ( parent_line_width / 2 ) ) , Point2i ( parent_pos . x , prev_hl_ofs ) , cache . parent_hl_line_color , parent_line_width ) ;
2021-06-21 15:46:43 +02:00
more_prev_ofs = cache . parent_hl_line_margin ;
2021-05-25 23:44:04 +02:00
prev_hl_ofs = root_pos . y + Math : : floor ( parent_line_width / 2 ) ;
2021-06-21 15:46:43 +02:00
} else if ( p_item - > is_selected ( 0 ) ) {
// If parent item is selected (but this item is not), we draw the line using children highlight style.
// Siblings of the selected branch can be drawn with a slight offset and their vertical line must appear as highlighted.
if ( _is_sibling_branch_selected ( c ) ) {
RenderingServer : : get_singleton ( ) - > canvas_item_add_line ( ci , root_pos , Point2i ( parent_pos . x + Math : : floor ( parent_line_width / 2 ) , root_pos . y ) , cache . children_hl_line_color , children_line_width ) ;
RenderingServer : : get_singleton ( ) - > canvas_item_add_line ( ci , Point2i ( parent_pos . x , root_pos . y + Math : : floor ( parent_line_width / 2 ) ) , Point2i ( parent_pos . x , prev_hl_ofs ) , cache . parent_hl_line_color , parent_line_width ) ;
prev_hl_ofs = root_pos . y + Math : : floor ( parent_line_width / 2 ) ;
} else {
RenderingServer : : get_singleton ( ) - > canvas_item_add_line ( ci , root_pos , Point2i ( parent_pos . x + Math : : floor ( children_line_width / 2 ) , root_pos . y ) , cache . children_hl_line_color , children_line_width ) ;
RenderingServer : : get_singleton ( ) - > canvas_item_add_line ( ci , Point2i ( parent_pos . x , root_pos . y + Math : : floor ( children_line_width / 2 ) ) , Point2i ( parent_pos . x , prev_ofs + Math : : floor ( children_line_width / 2 ) ) , cache . children_hl_line_color , children_line_width ) ;
}
2021-05-02 17:34:29 +02:00
} else {
2021-06-21 15:46:43 +02:00
// If nothing of the above is true, we draw the line using normal style.
// Siblings of the selected branch can be drawn with a slight offset and their vertical line must appear as highlighted.
if ( _is_sibling_branch_selected ( c ) ) {
RenderingServer : : get_singleton ( ) - > canvas_item_add_line ( ci , root_pos , Point2i ( parent_pos . x + cache . parent_hl_line_margin , root_pos . y ) , cache . relationship_line_color , line_width ) ;
RenderingServer : : get_singleton ( ) - > canvas_item_add_line ( ci , Point2i ( parent_pos . x , root_pos . y + Math : : floor ( parent_line_width / 2 ) ) , Point2i ( parent_pos . x , prev_hl_ofs ) , cache . parent_hl_line_color , parent_line_width ) ;
2021-05-25 23:44:04 +02:00
2021-06-21 15:46:43 +02:00
prev_hl_ofs = root_pos . y + Math : : floor ( parent_line_width / 2 ) ;
} else {
RenderingServer : : get_singleton ( ) - > canvas_item_add_line ( ci , root_pos , Point2i ( parent_pos . x + Math : : floor ( line_width / 2 ) , root_pos . y ) , cache . relationship_line_color , line_width ) ;
RenderingServer : : get_singleton ( ) - > canvas_item_add_line ( ci , Point2i ( parent_pos . x , root_pos . y + Math : : floor ( line_width / 2 ) ) , Point2i ( parent_pos . x , prev_ofs + Math : : floor ( line_width / 2 ) ) , cache . relationship_line_color , line_width ) ;
}
2021-05-02 17:34:29 +02:00
}
}
2018-01-04 10:03:46 +01:00
2021-06-21 15:46:43 +02:00
prev_ofs = root_pos . y + more_prev_ofs ;
2018-01-04 10:03:46 +01:00
}
2014-02-10 02:10:30 +01:00
2018-01-04 10:03:46 +01:00
if ( child_h < 0 ) {
if ( cache . draw_relationship_lines = = 0 ) {
return - 1 ; // break, stop drawing, no need to anymore
}
2021-05-02 17:34:29 +02:00
htotal = - 1 ;
children_pos . y = cache . offset . y + p_draw_size . height ;
2018-01-04 10:03:46 +01:00
} else {
htotal + = child_h ;
children_pos . y + = child_h ;
}
}
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
c = c - > next ;
2014-02-10 02:10:30 +01:00
}
}
return htotal ;
}
2017-03-05 16:44:50 +01:00
int Tree : : _count_selected_items ( TreeItem * p_from ) const {
int count = 0 ;
for ( int i = 0 ; i < columns . size ( ) ; i + + ) {
2020-05-14 16:41:43 +02:00
if ( p_from - > is_selected ( i ) ) {
2016-05-11 16:46:08 +02:00
count + + ;
2020-05-14 16:41:43 +02:00
}
2016-05-11 16:46:08 +02:00
}
2021-03-07 21:07:30 +01:00
if ( p_from - > get_first_child ( ) ) {
count + = _count_selected_items ( p_from - > get_first_child ( ) ) ;
2016-05-11 16:46:08 +02:00
}
if ( p_from - > get_next ( ) ) {
2017-03-05 16:44:50 +01:00
count + = _count_selected_items ( p_from - > get_next ( ) ) ;
2016-05-11 16:46:08 +02:00
}
return count ;
}
2020-05-14 14:29:06 +02:00
2021-05-02 17:34:29 +02:00
bool Tree : : _is_branch_selected ( TreeItem * p_from ) const {
for ( int i = 0 ; i < columns . size ( ) ; i + + ) {
if ( p_from - > is_selected ( i ) ) {
return true ;
}
}
TreeItem * child_item = p_from - > get_first_child ( ) ;
while ( child_item ) {
if ( _is_branch_selected ( child_item ) ) {
return true ;
}
child_item = child_item - > get_next ( ) ;
}
return false ;
}
bool Tree : : _is_sibling_branch_selected ( TreeItem * p_from ) const {
TreeItem * sibling_item = p_from - > get_next ( ) ;
while ( sibling_item ) {
if ( _is_branch_selected ( sibling_item ) ) {
return true ;
}
sibling_item = sibling_item - > get_next ( ) ;
}
return false ;
}
2016-07-09 18:14:46 +02:00
void Tree : : select_single_item ( TreeItem * p_selected , TreeItem * p_current , int p_col , TreeItem * p_prev , bool * r_in_range , bool p_force_deselect ) {
2018-07-25 03:11:03 +02:00
TreeItem : : Cell & selected_cell = p_selected - > cells . write [ p_col ] ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
bool switched = false ;
if ( r_in_range & & ! * r_in_range & & ( p_current = = p_selected | | p_current = = p_prev ) ) {
* r_in_range = true ;
switched = true ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
bool emitted_row = false ;
2016-06-30 22:51:45 +02:00
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < columns . size ( ) ; i + + ) {
2018-07-25 03:11:03 +02:00
TreeItem : : Cell & c = p_current - > cells . write [ i ] ;
2014-02-10 02:10:30 +01:00
2020-05-14 16:41:43 +02:00
if ( ! c . selectable ) {
2014-02-10 02:10:30 +01:00
continue ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
if ( select_mode = = SELECT_ROW ) {
2017-08-18 23:19:12 +02:00
if ( p_selected = = p_current & & ( ! c . selected | | allow_reselect ) ) {
2017-03-05 16:44:50 +01:00
c . selected = true ;
selected_item = p_selected ;
selected_col = 0 ;
if ( ! emitted_row ) {
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " item_selected " ) ) ;
2017-03-05 16:44:50 +01:00
emitted_row = true ;
}
/*
2017-01-14 12:26:56 +01:00
if ( p_col = = i )
p_current - > selected_signal . call ( p_col ) ;
*/
2015-08-31 00:37:23 +02:00
2016-12-20 22:47:24 +01:00
} else if ( c . selected ) {
2022-01-01 21:36:18 +01:00
if ( p_selected ! = p_current ) {
// Deselect other rows.
c . selected = false ;
}
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
} else if ( select_mode = = SELECT_SINGLE | | select_mode = = SELECT_MULTI ) {
if ( ! r_in_range & & & selected_cell = = & c ) {
2017-08-18 23:19:12 +02:00
if ( ! selected_cell . selected | | allow_reselect ) {
2017-03-05 16:44:50 +01:00
selected_cell . selected = true ;
2015-08-31 00:37:23 +02:00
2017-03-05 16:44:50 +01:00
selected_item = p_selected ;
selected_col = i ;
2015-08-30 04:46:32 +02:00
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " cell_selected " ) ) ;
2020-05-14 16:41:43 +02:00
if ( select_mode = = SELECT_MULTI ) {
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " multi_selected " ) , p_current , i , true ) ;
2020-05-14 16:41:43 +02:00
} else if ( select_mode = = SELECT_SINGLE ) {
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " item_selected " ) ) ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
} else if ( select_mode = = SELECT_MULTI & & ( selected_item ! = p_selected | | selected_col ! = i ) ) {
selected_item = p_selected ;
selected_col = i ;
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " cell_selected " ) ) ;
2014-02-10 02:10:30 +01:00
}
} else {
2016-07-09 18:14:46 +02:00
if ( r_in_range & & * r_in_range & & ! p_force_deselect ) {
2014-02-10 02:10:30 +01:00
if ( ! c . selected & & c . selectable ) {
2017-03-05 16:44:50 +01:00
c . selected = true ;
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " multi_selected " ) , p_current , i , true ) ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
} else if ( ! r_in_range | | p_force_deselect ) {
2020-05-14 16:41:43 +02:00
if ( select_mode = = SELECT_MULTI & & c . selected ) {
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " multi_selected " ) , p_current , i , false ) ;
2020-05-14 16:41:43 +02:00
}
2017-03-05 16:44:50 +01:00
c . selected = false ;
2014-02-10 02:10:30 +01:00
}
//p_current->deselected_signal.call(p_col);
}
}
}
2017-03-05 16:44:50 +01:00
if ( ! switched & & r_in_range & & * r_in_range & & ( p_current = = p_selected | | p_current = = p_prev ) ) {
* r_in_range = false ;
2014-02-10 02:10:30 +01:00
}
2021-03-07 21:07:30 +01:00
TreeItem * c = p_current - > first_child ;
2014-02-10 02:10:30 +01:00
while ( c ) {
2017-03-05 16:44:50 +01:00
select_single_item ( p_selected , c , p_col , p_prev , r_in_range , p_current - > is_collapsed ( ) | | p_force_deselect ) ;
c = c - > next ;
2014-02-10 02:10:30 +01:00
}
}
Rect2 Tree : : search_item_rect ( TreeItem * p_from , TreeItem * p_item ) {
return Rect2 ( ) ;
}
2015-12-08 19:04:56 +01:00
void Tree : : _range_click_timeout ( ) {
2021-08-13 23:31:57 +02:00
if ( range_item_last & & ! range_drag_enabled & & Input : : get_singleton ( ) - > is_mouse_button_pressed ( MouseButton : : LEFT ) ) {
2017-09-10 15:37:49 +02:00
Point2 pos = get_local_mouse_position ( ) - cache . bg - > get_offset ( ) ;
2015-12-08 19:04:56 +01:00
if ( show_column_titles ) {
2017-03-05 16:44:50 +01:00
pos . y - = _get_title_button_height ( ) ;
2015-12-08 19:04:56 +01:00
2017-03-05 16:44:50 +01:00
if ( pos . y < 0 ) {
2015-12-08 19:04:56 +01:00
range_click_timer - > stop ( ) ;
return ;
}
}
2021-06-24 07:54:00 +02:00
if ( ! root ) {
return ;
}
2017-03-05 16:44:50 +01:00
click_handled = false ;
2017-05-20 17:38:03 +02:00
Ref < InputEventMouseButton > mb ;
2021-06-18 00:03:09 +02:00
mb . instantiate ( ) ;
2015-12-08 19:04:56 +01:00
2021-07-04 05:13:28 +02:00
int x_limit = get_size ( ) . width - cache . bg - > get_minimum_size ( ) . width ;
if ( h_scroll - > is_visible ( ) ) {
x_limit - = h_scroll - > get_minimum_size ( ) . width ;
}
cache . rtl = is_layout_rtl ( ) ;
2019-02-13 09:23:29 +01:00
propagate_mouse_activated = false ; // done from outside, so signal handler can't clear the tree in the middle of emit (which is a common case)
2015-12-08 19:04:56 +01:00
blocked + + ;
2021-08-13 23:31:57 +02:00
propagate_mouse_event ( pos + cache . offset , 0 , 0 , x_limit + cache . offset . width , false , root , MouseButton : : LEFT , mb ) ;
2015-12-08 19:04:56 +01:00
blocked - - ;
if ( range_click_timer - > is_one_shot ( ) ) {
range_click_timer - > set_wait_time ( 0.05 ) ;
range_click_timer - > set_one_shot ( false ) ;
range_click_timer - > start ( ) ;
}
2020-05-14 16:41:43 +02:00
if ( ! click_handled ) {
2015-12-08 19:04:56 +01:00
range_click_timer - > stop ( ) ;
2020-05-14 16:41:43 +02:00
}
2015-12-08 19:04:56 +01:00
2019-01-14 21:20:33 +01:00
if ( propagate_mouse_activated ) {
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " item_activated " ) ) ;
2019-01-14 21:20:33 +01:00
propagate_mouse_activated = false ;
}
2015-12-08 19:04:56 +01:00
} else {
range_click_timer - > stop ( ) ;
}
}
2014-02-10 02:10:30 +01:00
2021-08-13 23:31:57 +02:00
int Tree : : propagate_mouse_event ( const Point2i & p_pos , int x_ofs , int y_ofs , int x_limit , bool p_double_click , TreeItem * p_item , MouseButton p_button , const Ref < InputEventWithModifiers > & p_mod ) {
2017-03-05 16:44:50 +01:00
int item_h = compute_item_height ( p_item ) + cache . vseparation ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
bool skip = ( p_item = = root & & hide_root ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
if ( ! skip & & p_pos . y < item_h ) {
2014-02-10 02:10:30 +01:00
// check event!
2016-01-21 14:08:40 +01:00
if ( range_click_timer - > get_time_left ( ) > 0 & & p_item ! = range_item_last ) {
return - 1 ;
}
2021-12-10 16:54:47 +01:00
if ( ! p_item - > disable_folding & & ! hide_folding & & p_item - > first_child & & ( p_pos . x > = x_ofs & & p_pos . x < ( x_ofs + cache . item_margin ) ) ) {
p_item - > set_collapsed ( ! p_item - > is_collapsed ( ) ) ;
return - 1 ;
2014-02-10 02:10:30 +01:00
}
2015-08-31 00:37:23 +02:00
2017-03-05 16:44:50 +01:00
int x = p_pos . x ;
2014-02-10 02:10:30 +01:00
/* find clicked column */
2017-03-05 16:44:50 +01:00
int col = - 1 ;
int col_ofs = 0 ;
int col_width = 0 ;
2021-07-04 05:13:28 +02:00
int limit_w = x_limit ;
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < columns . size ( ) ; i + + ) {
col_width = get_column_width ( i ) ;
2017-06-25 22:30:28 +02:00
if ( p_item - > cells [ i ] . expand_right ) {
int plus = 1 ;
2021-12-09 10:42:46 +01:00
while ( i + plus < columns . size ( ) & & ! p_item - > cells [ i + plus ] . editable & & p_item - > cells [ i + plus ] . mode = = TreeItem : : CELL_MODE_STRING & & p_item - > cells [ i + plus ] . text . is_empty ( ) & & p_item - > cells [ i + plus ] . icon . is_null ( ) ) {
2017-06-25 22:30:28 +02:00
col_width + = cache . hseparation ;
col_width + = get_column_width ( i + plus ) ;
plus + + ;
}
}
2017-03-05 16:44:50 +01:00
if ( x > col_width ) {
col_ofs + = col_width ;
x - = col_width ;
2021-07-04 05:13:28 +02:00
limit_w - = col_width ;
2014-02-10 02:10:30 +01:00
continue ;
}
2017-03-05 16:44:50 +01:00
col = i ;
2014-02-10 02:10:30 +01:00
break ;
}
2020-05-14 16:41:43 +02:00
if ( col = = - 1 ) {
2014-02-10 02:10:30 +01:00
return - 1 ;
2020-05-14 16:41:43 +02:00
} else if ( col = = 0 ) {
2017-03-05 16:44:50 +01:00
int margin = x_ofs + cache . item_margin ; //-cache.hseparation;
2020-12-22 17:24:29 +01:00
//int lm = cache.bg->get_margin(SIDE_LEFT);
2017-03-05 16:44:50 +01:00
col_width - = margin ;
2021-07-04 05:13:28 +02:00
limit_w - = margin ;
2017-03-05 16:44:50 +01:00
col_ofs + = margin ;
x - = margin ;
2014-02-10 02:10:30 +01:00
} else {
2017-03-05 16:44:50 +01:00
col_width - = cache . hseparation ;
2021-07-04 05:13:28 +02:00
limit_w - = cache . hseparation ;
2017-03-05 16:44:50 +01:00
x - = cache . hseparation ;
2014-02-10 02:10:30 +01:00
}
2021-03-07 21:07:30 +01:00
if ( ! p_item - > disable_folding & & ! hide_folding & & ! p_item - > cells [ col ] . editable & & ! p_item - > cells [ col ] . selectable & & p_item - > get_first_child ( ) ) {
2017-06-25 22:30:28 +02:00
p_item - > set_collapsed ( ! p_item - > is_collapsed ( ) ) ;
return - 1 ; //collapse/uncollapse because nothing can be done with item
}
2018-07-25 03:11:03 +02:00
const TreeItem : : Cell & c = p_item - > cells [ col ] ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
bool already_selected = c . selected ;
bool already_cursor = ( p_item = = selected_item ) & & col = = selected_col ;
2014-02-10 02:10:30 +01:00
2021-07-04 05:13:28 +02:00
if ( ! cache . rtl & & p_item - > cells [ col ] . buttons . size ( ) ) {
int button_w = 0 ;
for ( int j = p_item - > cells [ col ] . buttons . size ( ) - 1 ; j > = 0 ; j - - ) {
Ref < Texture2D > b = p_item - > cells [ col ] . buttons [ j ] . texture ;
button_w + = b - > get_size ( ) . width + cache . button_pressed - > get_minimum_size ( ) . width + cache . button_margin ;
}
col_width = MAX ( button_w , MIN ( limit_w , col_width ) ) ;
}
2017-03-05 16:44:50 +01:00
for ( int j = c . buttons . size ( ) - 1 ; j > = 0 ; j - - ) {
2019-06-11 20:43:37 +02:00
Ref < Texture2D > b = c . buttons [ j ] . texture ;
2014-02-10 02:10:30 +01:00
int w = b - > get_size ( ) . width + cache . button_pressed - > get_minimum_size ( ) . width ;
2016-02-03 00:44:42 +01:00
2017-03-05 16:44:50 +01:00
if ( x > col_width - w ) {
2016-02-03 00:44:42 +01:00
if ( c . buttons [ j ] . disabled ) {
2017-03-05 16:44:50 +01:00
pressed_button = - 1 ;
cache . click_type = Cache : : CLICK_NONE ;
2016-02-03 00:44:42 +01:00
return - 1 ;
}
2020-01-15 21:54:52 +01:00
// Make sure the click is correct.
Point2 click_pos = get_global_mouse_position ( ) - get_global_position ( ) ;
if ( ! get_item_at_position ( click_pos ) ) {
pressed_button = - 1 ;
cache . click_type = Cache : : CLICK_NONE ;
return - 1 ;
}
2017-03-05 16:44:50 +01:00
pressed_button = j ;
cache . click_type = Cache : : CLICK_BUTTON ;
cache . click_index = j ;
cache . click_id = c . buttons [ j ] . id ;
cache . click_item = p_item ;
cache . click_column = col ;
2020-01-15 21:54:52 +01:00
cache . click_pos = click_pos ;
2014-02-10 02:10:30 +01:00
update ( ) ;
2021-07-17 23:22:52 +02:00
//emit_signal(SNAME("button_pressed"));
2014-02-10 02:10:30 +01:00
return - 1 ;
}
2021-07-04 05:13:28 +02:00
2017-03-05 16:44:50 +01:00
col_width - = w + cache . button_margin ;
2014-02-10 02:10:30 +01:00
}
2021-08-13 23:31:57 +02:00
if ( p_button = = MouseButton : : LEFT | | ( p_button = = MouseButton : : RIGHT & & allow_rmb_select ) ) {
2014-02-10 02:10:30 +01:00
/* process selection */
2021-04-13 10:25:44 +02:00
if ( p_double_click & & ( ! c . editable | | c . mode = = TreeItem : : CELL_MODE_CUSTOM | | c . mode = = TreeItem : : CELL_MODE_ICON /*|| c.mode==TreeItem::CELL_MODE_CHECK*/ ) ) { //it's confusing for check
2014-02-10 02:10:30 +01:00
2019-01-14 21:20:33 +01:00
propagate_mouse_activated = true ;
2017-05-04 22:01:26 +02:00
incr_search . clear ( ) ;
2014-02-10 02:10:30 +01:00
return - 1 ;
}
2021-04-24 22:33:50 +02:00
if ( select_mode = = SELECT_MULTI & & p_mod - > is_command_pressed ( ) & & c . selectable ) {
2021-08-13 23:31:57 +02:00
if ( ! c . selected | | p_button = = MouseButton : : RIGHT ) {
2014-02-10 02:10:30 +01:00
p_item - > select ( col ) ;
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " multi_selected " ) , p_item , col , true ) ;
2021-08-13 23:31:57 +02:00
if ( p_button = = MouseButton : : RIGHT ) {
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " item_rmb_selected " ) , get_local_mouse_position ( ) ) ;
2016-05-16 04:41:48 +02:00
}
2014-02-10 02:10:30 +01:00
//p_item->selected_signal.call(col);
} else {
p_item - > deselect ( col ) ;
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " multi_selected " ) , p_item , col , false ) ;
2014-02-10 02:10:30 +01:00
//p_item->deselected_signal.call(col);
}
} else {
if ( c . selectable ) {
2021-04-24 22:33:50 +02:00
if ( select_mode = = SELECT_MULTI & & p_mod - > is_shift_pressed ( ) & & selected_item & & selected_item ! = p_item ) {
2017-03-05 16:44:50 +01:00
bool inrange = false ;
2015-08-30 04:46:32 +02:00
2017-03-05 16:44:50 +01:00
select_single_item ( p_item , root , col , selected_item , & inrange ) ;
2021-08-13 23:31:57 +02:00
if ( p_button = = MouseButton : : RIGHT ) {
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " item_rmb_selected " ) , get_local_mouse_position ( ) ) ;
2016-05-16 04:41:48 +02:00
}
2014-02-10 02:10:30 +01:00
} else {
2016-05-11 16:46:08 +02:00
int icount = _count_selected_items ( root ) ;
2021-08-13 23:31:57 +02:00
if ( select_mode = = SELECT_MULTI & & icount > 1 & & p_button ! = MouseButton : : RIGHT ) {
2017-03-05 16:44:50 +01:00
single_select_defer = p_item ;
single_select_defer_column = col ;
2016-05-11 16:46:08 +02:00
} else {
2021-08-13 23:31:57 +02:00
if ( p_button ! = MouseButton : : RIGHT | | ! c . selected ) {
2017-03-05 16:44:50 +01:00
select_single_item ( p_item , root , col ) ;
2016-05-16 04:41:48 +02:00
}
2021-08-13 23:31:57 +02:00
if ( p_button = = MouseButton : : RIGHT ) {
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " item_rmb_selected " ) , get_local_mouse_position ( ) ) ;
2016-05-16 04:41:48 +02:00
}
2016-05-11 16:46:08 +02:00
}
2014-02-10 02:10:30 +01:00
}
2017-01-14 12:26:56 +01:00
/*
if ( ! c . selected & & select_mode = = SELECT_MULTI ) {
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " multi_selected " ) , p_item , col , true ) ;
2017-01-14 12:26:56 +01:00
}
*/
2014-02-10 02:10:30 +01:00
update ( ) ;
}
}
}
2020-05-14 16:41:43 +02:00
if ( ! c . editable ) {
2014-02-10 02:10:30 +01:00
return - 1 ; // if cell is not editable, don't bother
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
/* editing */
2017-08-18 23:19:12 +02:00
bool bring_up_editor = allow_reselect ? ( c . selected & & already_selected ) : c . selected ;
2017-03-05 16:44:50 +01:00
String editor_text = c . text ;
2014-02-10 02:10:30 +01:00
switch ( c . mode ) {
case TreeItem : : CELL_MODE_STRING : {
//nothing in particular
2020-07-01 15:59:42 +02:00
if ( select_mode = = SELECT_MULTI & & ( get_viewport ( ) - > get_processed_events_count ( ) = = focus_in_id | | ! already_cursor ) ) {
2017-03-05 16:44:50 +01:00
bring_up_editor = false ;
2014-02-10 02:10:30 +01:00
}
} break ;
case TreeItem : : CELL_MODE_CHECK : {
2017-03-05 16:44:50 +01:00
bring_up_editor = false ; //checkboxes are not edited with editor
2017-01-21 23:00:25 +01:00
if ( force_edit_checkbox_only_on_checkbox ) {
if ( x < cache . checked - > get_width ( ) ) {
p_item - > set_checked ( col , ! c . checked ) ;
item_edited ( col , p_item ) ;
}
} else {
p_item - > set_checked ( col , ! c . checked ) ;
item_edited ( col , p_item ) ;
}
2016-09-19 23:07:24 +02:00
click_handled = true ;
//p_item->edited_signal.call(col);
2014-02-10 02:10:30 +01:00
} break ;
2018-09-22 22:31:56 +02:00
case TreeItem : : CELL_MODE_RANGE : {
2021-12-09 10:42:46 +01:00
if ( ! c . text . is_empty ( ) ) {
2014-02-10 02:10:30 +01:00
//if (x >= (get_column_width(col)-item_h/2)) {
popup_menu - > clear ( ) ;
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < c . text . get_slice_count ( " , " ) ; i + + ) {
String s = c . text . get_slicec ( ' , ' , i ) ;
2020-12-15 13:04:21 +01:00
popup_menu - > add_item ( s . get_slicec ( ' : ' , 0 ) , s . get_slicec ( ' : ' , 1 ) . is_empty ( ) ? i : s . get_slicec ( ' : ' , 1 ) . to_int ( ) ) ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
popup_menu - > set_size ( Size2 ( col_width , 0 ) ) ;
2021-08-31 17:43:35 +02:00
popup_menu - > set_position ( get_screen_position ( ) + Point2i ( col_ofs , _get_title_button_height ( ) + y_ofs + item_h ) - cache . offset ) ;
2014-02-10 02:10:30 +01:00
popup_menu - > popup ( ) ;
2017-03-05 16:44:50 +01:00
popup_edited_item = p_item ;
popup_edited_item_col = col ;
2014-02-10 02:10:30 +01:00
//}
2017-03-05 16:44:50 +01:00
bring_up_editor = false ;
2014-02-10 02:10:30 +01:00
} else {
2017-03-05 16:44:50 +01:00
if ( x > = ( col_width - item_h / 2 ) ) {
2014-02-10 02:10:30 +01:00
/* touching the combo */
2017-03-05 16:44:50 +01:00
bool up = p_pos . y < ( item_h / 2 ) ;
2015-08-31 00:37:23 +02:00
2021-08-13 23:31:57 +02:00
if ( p_button = = MouseButton : : LEFT ) {
2015-12-08 19:04:56 +01:00
if ( range_click_timer - > get_time_left ( ) = = 0 ) {
2017-03-05 16:44:50 +01:00
range_item_last = p_item ;
range_up_last = up ;
2015-12-08 19:04:56 +01:00
range_click_timer - > set_wait_time ( 0.6 ) ;
range_click_timer - > set_one_shot ( true ) ;
range_click_timer - > start ( ) ;
} else if ( up ! = range_up_last ) {
return - 1 ; // break. avoid changing direction on mouse held
}
2017-03-05 16:44:50 +01:00
p_item - > set_range ( col , c . val + ( up ? 1.0 : - 1.0 ) * c . step ) ;
2015-08-31 00:37:23 +02:00
2017-03-05 16:44:50 +01:00
item_edited ( col , p_item ) ;
2015-12-08 19:04:56 +01:00
2021-08-13 23:31:57 +02:00
} else if ( p_button = = MouseButton : : RIGHT ) {
2017-03-05 16:44:50 +01:00
p_item - > set_range ( col , ( up ? c . max : c . min ) ) ;
item_edited ( col , p_item ) ;
2021-08-13 23:31:57 +02:00
} else if ( p_button = = MouseButton : : WHEEL_UP ) {
2017-03-05 16:44:50 +01:00
p_item - > set_range ( col , c . val + c . step ) ;
item_edited ( col , p_item ) ;
2021-08-13 23:31:57 +02:00
} else if ( p_button = = MouseButton : : WHEEL_DOWN ) {
2017-03-05 16:44:50 +01:00
p_item - > set_range ( col , c . val - c . step ) ;
item_edited ( col , p_item ) ;
2014-02-10 02:10:30 +01:00
}
2015-08-31 00:37:23 +02:00
//p_item->edited_signal.call(col);
2017-03-05 16:44:50 +01:00
bring_up_editor = false ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
} else {
2019-07-23 17:27:55 +02:00
editor_text = String : : num ( p_item - > cells [ col ] . val , Math : : range_step_decimals ( p_item - > cells [ col ] . step ) ) ;
2020-07-01 15:59:42 +02:00
if ( select_mode = = SELECT_MULTI & & get_viewport ( ) - > get_processed_events_count ( ) = = focus_in_id ) {
2017-03-05 16:44:50 +01:00
bring_up_editor = false ;
2020-05-14 16:41:43 +02:00
}
2015-08-31 00:37:23 +02:00
}
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
click_handled = true ;
2014-02-10 02:10:30 +01:00
} break ;
case TreeItem : : CELL_MODE_ICON : {
2017-03-05 16:44:50 +01:00
bring_up_editor = false ;
2014-02-10 02:10:30 +01:00
} break ;
case TreeItem : : CELL_MODE_CUSTOM : {
2017-03-05 16:44:50 +01:00
edited_item = p_item ;
edited_col = col ;
2017-06-05 01:35:08 +02:00
bool on_arrow = x > col_width - cache . select_arrow - > get_width ( ) ;
2017-03-05 16:44:50 +01:00
2017-08-10 21:02:19 +02:00
custom_popup_rect = Rect2i ( get_global_position ( ) + Point2i ( col_ofs , _get_title_button_height ( ) + y_ofs + item_h - cache . offset . y ) , Size2 ( get_column_width ( col ) , item_h ) ) ;
2017-06-05 01:35:08 +02:00
if ( on_arrow | | ! p_item - > cells [ col ] . custom_button ) {
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " custom_popup_edited " ) , ( ( bool ) ( x > = ( col_width - item_h / 2 ) ) ) ) ;
2017-06-05 01:35:08 +02:00
}
if ( ! p_item - > cells [ col ] . custom_button | | ! on_arrow ) {
2021-08-13 23:31:57 +02:00
item_edited ( col , p_item , p_button = = MouseButton : : LEFT ) ;
2017-06-05 01:35:08 +02:00
}
2017-03-05 16:44:50 +01:00
click_handled = true ;
2014-02-10 02:10:30 +01:00
return - 1 ;
} break ;
} ;
2021-08-13 23:31:57 +02:00
if ( ! bring_up_editor | | p_button ! = MouseButton : : LEFT ) {
2014-02-10 02:10:30 +01:00
return - 1 ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
click_handled = true ;
popup_edited_item = p_item ;
popup_edited_item_col = col ;
2014-02-10 02:10:30 +01:00
2017-03-29 17:29:38 +02:00
pressing_item_rect = Rect2 ( get_global_position ( ) + Point2i ( col_ofs , _get_title_button_height ( ) + y_ofs ) - cache . offset , Size2 ( col_width , item_h ) ) ;
2017-03-05 16:44:50 +01:00
pressing_for_editor_text = editor_text ;
pressing_for_editor = true ;
2014-02-10 02:10:30 +01:00
return - 1 ; //select
} else {
2017-03-05 16:44:50 +01:00
Point2i new_pos = p_pos ;
2015-08-31 00:37:23 +02:00
2014-02-10 02:10:30 +01:00
if ( ! skip ) {
2017-03-05 16:44:50 +01:00
x_ofs + = cache . item_margin ;
2014-02-10 02:10:30 +01:00
//new_pos.x-=cache.item_margin;
2017-03-05 16:44:50 +01:00
y_ofs + = item_h ;
new_pos . y - = item_h ;
2014-02-10 02:10:30 +01:00
}
2015-08-31 00:37:23 +02:00
2018-01-18 21:37:17 +01:00
if ( ! p_item - > collapsed ) { /* if not collapsed, check the children */
2014-02-10 02:10:30 +01:00
2021-03-07 21:07:30 +01:00
TreeItem * c = p_item - > first_child ;
2014-02-10 02:10:30 +01:00
while ( c ) {
2021-07-04 05:13:28 +02:00
int child_h = propagate_mouse_event ( new_pos , x_ofs , y_ofs , x_limit , p_double_click , c , p_button , p_mod ) ;
2014-02-10 02:10:30 +01:00
2020-05-14 16:41:43 +02:00
if ( child_h < 0 ) {
2014-02-10 02:10:30 +01:00
return - 1 ; // break, stop propagating, no need to anymore
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
new_pos . y - = child_h ;
y_ofs + = child_h ;
c = c - > next ;
item_h + = child_h ;
2014-02-10 02:10:30 +01:00
}
}
2021-08-13 23:31:57 +02:00
if ( p_item = = root & & p_button = = MouseButton : : RIGHT ) {
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " empty_rmb " ) , get_local_mouse_position ( ) ) ;
2019-04-09 19:22:14 +02:00
}
2014-02-10 02:10:30 +01:00
}
return item_h ; // nothing found
}
2016-01-23 15:45:36 +01:00
void Tree : : _text_editor_modal_close ( ) {
2021-08-13 23:31:57 +02:00
if ( Input : : get_singleton ( ) - > is_key_pressed ( Key : : ESCAPE ) | |
Input : : get_singleton ( ) - > is_key_pressed ( Key : : KP_ENTER ) | |
Input : : get_singleton ( ) - > is_key_pressed ( Key : : ENTER ) ) {
2016-01-23 15:45:36 +01:00
return ;
}
2020-05-14 16:41:43 +02:00
if ( value_editor - > has_point ( value_editor - > get_local_mouse_position ( ) ) ) {
2016-01-27 16:24:49 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2016-01-23 15:45:36 +01:00
2021-06-16 18:43:34 +02:00
_text_editor_submit ( text_editor - > get_text ( ) ) ;
2016-01-23 15:45:36 +01:00
}
2021-06-16 18:43:34 +02:00
void Tree : : _text_editor_submit ( String p_text ) {
2020-03-20 03:32:09 +01:00
popup_editor - > hide ( ) ;
2014-02-10 02:10:30 +01:00
2020-05-14 16:41:43 +02:00
if ( ! popup_edited_item ) {
2014-02-10 02:10:30 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2020-05-14 16:41:43 +02:00
if ( popup_edited_item_col < 0 | | popup_edited_item_col > columns . size ( ) ) {
2014-02-10 02:10:30 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2018-07-25 03:11:03 +02:00
TreeItem : : Cell & c = popup_edited_item - > cells . write [ popup_edited_item_col ] ;
2017-03-05 16:44:50 +01:00
switch ( c . mode ) {
2014-02-10 02:10:30 +01:00
case TreeItem : : CELL_MODE_STRING : {
2017-03-05 16:44:50 +01:00
c . text = p_text ;
2014-02-10 02:10:30 +01:00
//popup_edited_item->edited_signal.call( popup_edited_item_col );
} break ;
case TreeItem : : CELL_MODE_RANGE : {
2020-07-24 20:07:57 +02:00
c . val = p_text . to_float ( ) ;
2020-05-14 16:41:43 +02:00
if ( c . step > 0 ) {
2020-12-21 19:02:57 +01:00
c . val = Math : : snapped ( c . val , c . step ) ;
2020-05-14 16:41:43 +02:00
}
if ( c . val < c . min ) {
2017-03-05 16:44:50 +01:00
c . val = c . min ;
2020-05-14 16:41:43 +02:00
} else if ( c . val > c . max ) {
2017-03-05 16:44:50 +01:00
c . val = c . max ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
//popup_edited_item->edited_signal.call( popup_edited_item_col );
} break ;
2019-04-09 17:08:36 +02:00
default : {
ERR_FAIL ( ) ;
}
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
item_edited ( popup_edited_item_col , popup_edited_item ) ;
2014-02-10 02:10:30 +01:00
update ( ) ;
}
void Tree : : value_editor_changed ( double p_value ) {
if ( updating_value_editor ) {
return ;
}
if ( ! popup_edited_item ) {
return ;
}
2018-07-25 03:11:03 +02:00
TreeItem : : Cell & c = popup_edited_item - > cells . write [ popup_edited_item_col ] ;
2017-03-05 16:44:50 +01:00
c . val = p_value ;
item_edited ( popup_edited_item_col , popup_edited_item ) ;
2014-02-10 02:10:30 +01:00
update ( ) ;
}
void Tree : : popup_select ( int p_option ) {
2020-05-14 16:41:43 +02:00
if ( ! popup_edited_item ) {
2014-02-10 02:10:30 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2020-05-14 16:41:43 +02:00
if ( popup_edited_item_col < 0 | | popup_edited_item_col > columns . size ( ) ) {
2014-02-10 02:10:30 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2018-07-25 03:11:03 +02:00
popup_edited_item - > cells . write [ popup_edited_item_col ] . val = p_option ;
2014-02-10 02:10:30 +01:00
//popup_edited_item->edited_signal.call( popup_edited_item_col );
update ( ) ;
2017-03-05 16:44:50 +01:00
item_edited ( popup_edited_item_col , popup_edited_item ) ;
2014-02-10 02:10:30 +01:00
}
2017-12-31 05:56:17 +01:00
void Tree : : _go_left ( ) {
if ( selected_col = = 0 ) {
2021-03-07 21:07:30 +01:00
if ( selected_item - > get_first_child ( ) ! = nullptr & & ! selected_item - > is_collapsed ( ) ) {
2017-12-31 05:56:17 +01:00
selected_item - > set_collapsed ( true ) ;
} else {
if ( columns . size ( ) = = 1 ) { // goto parent with one column
TreeItem * parent = selected_item - > get_parent ( ) ;
if ( selected_item ! = get_root ( ) & & parent & & parent - > is_selectable ( selected_col ) & & ! ( hide_root & & parent = = get_root ( ) ) ) {
select_single_item ( parent , get_root ( ) , selected_col ) ;
}
} else if ( selected_item - > get_prev_visible ( ) ) {
selected_col = columns . size ( ) - 1 ;
_go_up ( ) ; // go to upper column if possible
}
}
} else {
if ( select_mode = = SELECT_MULTI ) {
selected_col - - ;
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " cell_selected " ) ) ;
2017-12-31 05:56:17 +01:00
} else {
selected_item - > select ( selected_col - 1 ) ;
}
}
update ( ) ;
accept_event ( ) ;
ensure_cursor_is_visible ( ) ;
}
2014-02-10 02:10:30 +01:00
2017-12-31 05:56:17 +01:00
void Tree : : _go_right ( ) {
if ( selected_col = = ( columns . size ( ) - 1 ) ) {
2021-03-07 21:07:30 +01:00
if ( selected_item - > get_first_child ( ) ! = nullptr & & selected_item - > is_collapsed ( ) ) {
2017-12-31 05:56:17 +01:00
selected_item - > set_collapsed ( false ) ;
} else if ( selected_item - > get_next_visible ( ) ) {
2020-01-01 10:57:40 +01:00
selected_col = 0 ;
2017-12-31 05:56:17 +01:00
_go_down ( ) ;
}
} else {
if ( select_mode = = SELECT_MULTI ) {
selected_col + + ;
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " cell_selected " ) ) ;
2017-12-31 05:56:17 +01:00
} else {
selected_item - > select ( selected_col + 1 ) ;
}
}
update ( ) ;
ensure_cursor_is_visible ( ) ;
accept_event ( ) ;
}
void Tree : : _go_up ( ) {
2020-04-02 01:20:12 +02:00
TreeItem * prev = nullptr ;
2017-12-31 05:56:17 +01:00
if ( ! selected_item ) {
prev = get_last_item ( ) ;
selected_col = 0 ;
} else {
prev = selected_item - > get_prev_visible ( ) ;
if ( last_keypress ! = 0 ) {
//incr search next
int col ;
prev = _search_item_text ( prev , incr_search , & col , true , true ) ;
if ( ! prev ) {
accept_event ( ) ;
return ;
}
}
}
if ( select_mode = = SELECT_MULTI ) {
2020-05-14 16:41:43 +02:00
if ( ! prev ) {
2017-05-20 17:38:03 +02:00
return ;
2020-05-14 16:41:43 +02:00
}
2017-12-31 05:56:17 +01:00
selected_item = prev ;
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " cell_selected " ) ) ;
2017-12-31 05:56:17 +01:00
update ( ) ;
} else {
int col = selected_col < 0 ? 0 : selected_col ;
2020-05-14 16:41:43 +02:00
while ( prev & & ! prev - > cells [ col ] . selectable ) {
2017-12-31 05:56:17 +01:00
prev = prev - > get_prev_visible ( ) ;
2020-05-14 16:41:43 +02:00
}
if ( ! prev ) {
2017-12-31 05:56:17 +01:00
return ; // do nothing..
2020-05-14 16:41:43 +02:00
}
2017-12-31 05:56:17 +01:00
prev - > select ( col ) ;
2017-03-05 16:44:50 +01:00
}
2014-02-10 02:10:30 +01:00
2017-12-31 05:56:17 +01:00
ensure_cursor_is_visible ( ) ;
accept_event ( ) ;
}
void Tree : : _go_down ( ) {
2020-04-02 01:20:12 +02:00
TreeItem * next = nullptr ;
2017-12-31 05:56:17 +01:00
if ( ! selected_item ) {
2019-11-12 08:15:29 +01:00
if ( root ) {
next = hide_root ? root - > get_next_visible ( ) : root ;
}
2017-12-31 05:56:17 +01:00
} else {
next = selected_item - > get_next_visible ( ) ;
if ( last_keypress ! = 0 ) {
//incr search next
int col ;
next = _search_item_text ( next , incr_search , & col , true ) ;
if ( ! next ) {
2017-05-20 17:38:03 +02:00
accept_event ( ) ;
2017-12-31 05:56:17 +01:00
return ;
2017-09-16 18:26:05 +02:00
}
2017-12-31 05:56:17 +01:00
}
}
2014-02-10 02:10:30 +01:00
2017-12-31 05:56:17 +01:00
if ( select_mode = = SELECT_MULTI ) {
if ( ! next ) {
return ;
}
2014-02-10 02:10:30 +01:00
2017-12-31 05:56:17 +01:00
selected_item = next ;
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " cell_selected " ) ) ;
2017-12-31 05:56:17 +01:00
update ( ) ;
} else {
int col = selected_col < 0 ? 0 : selected_col ;
2014-02-10 02:10:30 +01:00
2020-05-14 16:41:43 +02:00
while ( next & & ! next - > cells [ col ] . selectable ) {
2017-12-31 05:56:17 +01:00
next = next - > get_next_visible ( ) ;
2020-05-14 16:41:43 +02:00
}
2017-12-31 05:56:17 +01:00
if ( ! next ) {
return ; // do nothing..
}
next - > select ( col ) ;
}
2014-02-10 02:10:30 +01:00
2017-12-31 05:56:17 +01:00
ensure_cursor_is_visible ( ) ;
accept_event ( ) ;
}
2014-02-10 02:10:30 +01:00
2021-08-22 17:37:22 +02:00
void Tree : : gui_input ( const Ref < InputEvent > & p_event ) {
2021-04-05 08:52:21 +02:00
ERR_FAIL_COND ( p_event . is_null ( ) ) ;
2017-12-31 05:56:17 +01:00
Ref < InputEventKey > k = p_event ;
2014-02-10 02:10:30 +01:00
2021-04-24 22:33:50 +02:00
bool is_command = k . is_valid ( ) & & k - > is_command_pressed ( ) ;
2017-12-31 05:56:17 +01:00
if ( p_event - > is_action ( " ui_right " ) & & p_event - > is_pressed ( ) ) {
2020-05-14 16:41:43 +02:00
if ( ! cursor_can_exit_tree ) {
2020-05-10 12:56:01 +02:00
accept_event ( ) ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2017-12-31 05:56:17 +01:00
if ( ! selected_item | | select_mode = = SELECT_ROW | | selected_col > ( columns . size ( ) - 1 ) ) {
return ;
}
2021-04-24 22:33:50 +02:00
if ( k . is_valid ( ) & & k - > is_alt_pressed ( ) ) {
2017-12-31 05:56:17 +01:00
selected_item - > set_collapsed ( false ) ;
2021-03-07 21:07:30 +01:00
TreeItem * next = selected_item - > get_first_child ( ) ;
2017-12-31 05:56:17 +01:00
while ( next & & next ! = selected_item - > next ) {
next - > set_collapsed ( false ) ;
next = next - > get_next_visible ( ) ;
}
} else {
_go_right ( ) ;
}
} else if ( p_event - > is_action ( " ui_left " ) & & p_event - > is_pressed ( ) ) {
2020-05-14 16:41:43 +02:00
if ( ! cursor_can_exit_tree ) {
2020-05-10 12:56:01 +02:00
accept_event ( ) ;
2020-05-14 16:41:43 +02:00
}
2017-09-16 18:26:05 +02:00
2017-12-31 05:56:17 +01:00
if ( ! selected_item | | select_mode = = SELECT_ROW | | selected_col < 0 ) {
return ;
}
2021-04-24 22:33:50 +02:00
if ( k . is_valid ( ) & & k - > is_alt_pressed ( ) ) {
2017-12-31 05:56:17 +01:00
selected_item - > set_collapsed ( true ) ;
2021-03-07 21:07:30 +01:00
TreeItem * next = selected_item - > get_first_child ( ) ;
2017-12-31 05:56:17 +01:00
while ( next & & next ! = selected_item - > next ) {
next - > set_collapsed ( true ) ;
next = next - > get_next_visible ( ) ;
2017-09-16 18:26:05 +02:00
}
2017-12-31 05:56:17 +01:00
} else {
_go_left ( ) ;
}
2014-02-10 02:10:30 +01:00
2018-10-07 16:22:04 +02:00
} else if ( p_event - > is_action ( " ui_up " ) & & p_event - > is_pressed ( ) & & ! is_command ) {
2020-05-14 16:41:43 +02:00
if ( ! cursor_can_exit_tree ) {
2020-05-10 12:56:01 +02:00
accept_event ( ) ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2017-12-31 05:56:17 +01:00
_go_up ( ) ;
2014-02-10 02:10:30 +01:00
2018-10-07 16:22:04 +02:00
} else if ( p_event - > is_action ( " ui_down " ) & & p_event - > is_pressed ( ) & & ! is_command ) {
2020-05-14 16:41:43 +02:00
if ( ! cursor_can_exit_tree ) {
2020-05-10 12:56:01 +02:00
accept_event ( ) ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2017-12-31 05:56:17 +01:00
_go_down ( ) ;
2014-02-10 02:10:30 +01:00
2017-12-31 05:56:17 +01:00
} else if ( p_event - > is_action ( " ui_page_down " ) & & p_event - > is_pressed ( ) ) {
2020-05-14 16:41:43 +02:00
if ( ! cursor_can_exit_tree ) {
2020-05-10 12:56:01 +02:00
accept_event ( ) ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2020-04-02 01:20:12 +02:00
TreeItem * next = nullptr ;
2020-05-14 16:41:43 +02:00
if ( ! selected_item ) {
2017-12-31 05:56:17 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2017-12-31 05:56:17 +01:00
next = selected_item ;
2014-02-10 02:10:30 +01:00
2017-12-31 05:56:17 +01:00
for ( int i = 0 ; i < 10 ; i + + ) {
TreeItem * _n = next - > get_next_visible ( ) ;
if ( _n ) {
next = _n ;
} else {
2019-05-20 20:34:55 +02:00
break ;
2017-12-31 05:56:17 +01:00
}
}
2020-05-14 16:41:43 +02:00
if ( next = = selected_item ) {
2017-12-31 05:56:17 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2017-12-31 05:56:17 +01:00
if ( select_mode = = SELECT_MULTI ) {
selected_item = next ;
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " cell_selected " ) ) ;
2017-12-31 05:56:17 +01:00
update ( ) ;
} else {
2020-05-14 16:41:43 +02:00
while ( next & & ! next - > cells [ selected_col ] . selectable ) {
2017-12-31 05:56:17 +01:00
next = next - > get_next_visible ( ) ;
2020-05-14 16:41:43 +02:00
}
2017-12-31 05:56:17 +01:00
if ( ! next ) {
return ; // do nothing..
}
next - > select ( selected_col ) ;
}
2014-02-10 02:10:30 +01:00
2017-12-31 05:56:17 +01:00
ensure_cursor_is_visible ( ) ;
} else if ( p_event - > is_action ( " ui_page_up " ) & & p_event - > is_pressed ( ) ) {
2020-05-14 16:41:43 +02:00
if ( ! cursor_can_exit_tree ) {
2020-05-10 12:56:01 +02:00
accept_event ( ) ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2020-04-02 01:20:12 +02:00
TreeItem * prev = nullptr ;
2020-05-14 16:41:43 +02:00
if ( ! selected_item ) {
2017-12-31 05:56:17 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2017-12-31 05:56:17 +01:00
prev = selected_item ;
2014-02-10 02:10:30 +01:00
2017-12-31 05:56:17 +01:00
for ( int i = 0 ; i < 10 ; i + + ) {
TreeItem * _n = prev - > get_prev_visible ( ) ;
if ( _n ) {
prev = _n ;
} else {
2019-05-20 20:34:55 +02:00
break ;
2017-12-31 05:56:17 +01:00
}
}
2020-05-14 16:41:43 +02:00
if ( prev = = selected_item ) {
2017-12-31 05:56:17 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2017-12-31 05:56:17 +01:00
if ( select_mode = = SELECT_MULTI ) {
selected_item = prev ;
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " cell_selected " ) ) ;
2017-12-31 05:56:17 +01:00
update ( ) ;
} else {
2020-05-14 16:41:43 +02:00
while ( prev & & ! prev - > cells [ selected_col ] . selectable ) {
2017-12-31 05:56:17 +01:00
prev = prev - > get_prev_visible ( ) ;
2020-05-14 16:41:43 +02:00
}
2017-12-31 05:56:17 +01:00
if ( ! prev ) {
return ; // do nothing..
}
prev - > select ( selected_col ) ;
}
ensure_cursor_is_visible ( ) ;
} else if ( p_event - > is_action ( " ui_accept " ) & & p_event - > is_pressed ( ) ) {
if ( selected_item ) {
//bring up editor if possible
if ( ! edit_selected ( ) ) {
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " item_activated " ) ) ;
2017-12-31 05:56:17 +01:00
incr_search . clear ( ) ;
}
}
accept_event ( ) ;
} else if ( p_event - > is_action ( " ui_select " ) & & p_event - > is_pressed ( ) ) {
if ( select_mode = = SELECT_MULTI ) {
2020-05-14 16:41:43 +02:00
if ( ! selected_item ) {
2017-12-31 05:56:17 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2017-12-31 05:56:17 +01:00
if ( selected_item - > is_selected ( selected_col ) ) {
selected_item - > deselect ( selected_col ) ;
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " multi_selected " ) , selected_item , selected_col , false ) ;
2017-12-31 05:56:17 +01:00
} else if ( selected_item - > is_selectable ( selected_col ) ) {
selected_item - > select ( selected_col ) ;
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " multi_selected " ) , selected_item , selected_col , true ) ;
2017-12-31 05:56:17 +01:00
}
}
accept_event ( ) ;
}
2014-02-10 02:10:30 +01:00
2017-12-31 05:56:17 +01:00
if ( k . is_valid ( ) ) { // Incremental search
2020-05-14 16:41:43 +02:00
if ( ! k - > is_pressed ( ) ) {
2017-12-31 05:56:17 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2021-04-24 22:33:50 +02:00
if ( k - > is_command_pressed ( ) | | ( k - > is_shift_pressed ( ) & & k - > get_unicode ( ) = = 0 ) | | k - > is_meta_pressed ( ) ) {
2017-12-31 05:56:17 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
if ( ! root ) {
2017-12-31 05:56:17 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2020-05-14 16:41:43 +02:00
if ( hide_root & & ! root - > get_next_visible ( ) ) {
2017-12-31 05:56:17 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2017-12-31 05:56:17 +01:00
if ( k - > get_unicode ( ) > 0 ) {
_do_incr_search ( String : : chr ( k - > get_unicode ( ) ) ) ;
accept_event ( ) ;
return ;
} else {
2021-08-13 23:31:57 +02:00
if ( k - > get_keycode ( ) ! = Key : : SHIFT ) {
2017-12-31 05:56:17 +01:00
last_keypress = 0 ;
2020-05-14 16:41:43 +02:00
}
2017-05-20 17:38:03 +02:00
}
}
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
Ref < InputEventMouseMotion > mm = p_event ;
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
if ( mm . is_valid ( ) ) {
2020-05-14 16:41:43 +02:00
if ( cache . font . is_null ( ) ) { // avoid a strange case that may corrupt stuff
2017-05-20 17:38:03 +02:00
update_cache ( ) ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
Ref < StyleBox > bg = cache . bg ;
2020-09-03 13:22:16 +02:00
bool rtl = is_layout_rtl ( ) ;
2014-02-10 02:10:30 +01:00
2020-09-03 13:22:16 +02:00
Point2 pos = mm - > get_position ( ) ;
if ( rtl ) {
pos . x = get_size ( ) . width - pos . x ;
}
pos - = cache . bg - > get_offset ( ) ;
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
Cache : : ClickType old_hover = cache . hover_type ;
int old_index = cache . hover_index ;
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
cache . hover_type = Cache : : CLICK_NONE ;
cache . hover_index = 0 ;
if ( show_column_titles ) {
pos . y - = _get_title_button_height ( ) ;
if ( pos . y < 0 ) {
pos . x + = cache . offset . x ;
int len = 0 ;
for ( int i = 0 ; i < columns . size ( ) ; i + + ) {
len + = get_column_width ( i ) ;
if ( pos . x < len ) {
cache . hover_type = Cache : : CLICK_TITLE ;
cache . hover_index = i ;
break ;
2014-02-10 02:10:30 +01:00
}
}
}
2017-05-20 17:38:03 +02:00
}
2014-02-10 02:10:30 +01:00
2017-06-05 01:35:08 +02:00
if ( root ) {
2017-06-03 10:54:24 +02:00
Point2 mpos = mm - > get_position ( ) ;
2020-09-03 13:22:16 +02:00
if ( rtl ) {
mpos . x = get_size ( ) . width - mpos . x ;
}
2017-05-20 17:38:03 +02:00
mpos - = cache . bg - > get_offset ( ) ;
mpos . y - = _get_title_button_height ( ) ;
if ( mpos . y > = 0 ) {
2020-05-14 16:41:43 +02:00
if ( h_scroll - > is_visible_in_tree ( ) ) {
2017-05-20 17:38:03 +02:00
mpos . x + = h_scroll - > get_value ( ) ;
2020-05-14 16:41:43 +02:00
}
if ( v_scroll - > is_visible_in_tree ( ) ) {
2017-05-20 17:38:03 +02:00
mpos . y + = v_scroll - > get_value ( ) ;
2020-05-14 16:41:43 +02:00
}
2016-05-11 16:46:08 +02:00
2020-06-06 23:02:22 +02:00
TreeItem * old_it = cache . hover_item ;
int old_col = cache . hover_cell ;
2017-05-20 17:38:03 +02:00
int col , h , section ;
TreeItem * it = _find_item_at_pos ( root , mpos , col , h , section ) ;
2016-05-11 16:46:08 +02:00
2018-07-13 15:00:10 +02:00
if ( drop_mode_flags ) {
if ( it ! = drop_mode_over ) {
drop_mode_over = it ;
update ( ) ;
}
if ( it & & section ! = drop_mode_section ) {
drop_mode_section = section ;
update ( ) ;
}
2016-05-11 16:46:08 +02:00
}
2017-06-05 01:35:08 +02:00
2020-06-06 23:02:22 +02:00
cache . hover_item = it ;
cache . hover_cell = col ;
2018-07-13 15:00:10 +02:00
2020-06-06 23:02:22 +02:00
if ( it ! = old_it | | col ! = old_col ) {
2020-09-08 11:20:07 +02:00
if ( old_it & & old_col > = old_it - > cells . size ( ) ) {
// Columns may have changed since last update().
2020-06-06 23:02:22 +02:00
update ( ) ;
2020-09-08 11:20:07 +02:00
} else {
// Only need to update if mouse enters/exits a button
bool was_over_button = old_it & & old_it - > cells [ old_col ] . custom_button ;
bool is_over_button = it & & it - > cells [ col ] . custom_button ;
if ( was_over_button | | is_over_button ) {
update ( ) ;
}
2020-06-06 23:02:22 +02:00
}
2017-06-05 01:35:08 +02:00
}
2016-05-11 16:46:08 +02:00
}
2017-05-20 17:38:03 +02:00
}
2016-05-11 16:46:08 +02:00
2020-06-06 23:02:22 +02:00
// Update if mouse enters/exits columns
2017-05-20 17:38:03 +02:00
if ( cache . hover_type ! = old_hover | | cache . hover_index ! = old_index ) {
update ( ) ;
}
2015-08-29 06:43:21 +02:00
2018-09-22 22:31:56 +02:00
if ( pressing_for_editor & & popup_edited_item & & ( popup_edited_item - > get_cell_mode ( popup_edited_item_col ) = = TreeItem : : CELL_MODE_RANGE ) ) {
2017-05-20 17:38:03 +02:00
//range drag
2015-08-29 06:43:21 +02:00
2017-05-20 17:38:03 +02:00
if ( ! range_drag_enabled ) {
2017-06-03 10:54:24 +02:00
Vector2 cpos = mm - > get_position ( ) ;
2020-09-03 13:22:16 +02:00
if ( rtl ) {
cpos . x = get_size ( ) . width - cpos . x ;
}
2017-05-20 17:38:03 +02:00
if ( cpos . distance_to ( pressing_pos ) > 2 ) {
range_drag_enabled = true ;
range_drag_capture_pos = cpos ;
range_drag_base = popup_edited_item - > get_range ( popup_edited_item_col ) ;
2020-04-28 15:19:37 +02:00
Input : : get_singleton ( ) - > set_mouse_mode ( Input : : MOUSE_MODE_CAPTURED ) ;
2015-08-29 06:43:21 +02:00
}
2017-05-20 17:38:03 +02:00
} else {
2018-07-25 03:11:03 +02:00
const TreeItem : : Cell & c = popup_edited_item - > cells [ popup_edited_item_col ] ;
2017-05-20 17:38:03 +02:00
float diff_y = - mm - > get_relative ( ) . y ;
2021-10-16 01:22:57 +02:00
diff_y = Math : : pow ( ABS ( diff_y ) , 1.8f ) * SIGN ( diff_y ) ;
2017-05-20 17:38:03 +02:00
diff_y * = 0.1 ;
range_drag_base = CLAMP ( range_drag_base + c . step * diff_y , c . min , c . max ) ;
popup_edited_item - > set_range ( popup_edited_item_col , range_drag_base ) ;
item_edited ( popup_edited_item_col , popup_edited_item ) ;
2015-08-29 06:43:21 +02:00
}
2017-05-20 17:38:03 +02:00
}
2015-08-29 06:43:21 +02:00
2017-05-20 17:38:03 +02:00
if ( drag_touching & & ! drag_touching_deaccel ) {
drag_accum - = mm - > get_relative ( ) . y ;
v_scroll - > set_value ( drag_from + drag_accum ) ;
2021-12-29 14:22:22 +01:00
drag_speed = - mm - > get_velocity ( ) . y ;
2017-05-20 17:38:03 +02:00
}
}
2015-08-31 00:37:23 +02:00
2017-05-20 17:38:03 +02:00
Ref < InputEventMouseButton > b = p_event ;
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
if ( b . is_valid ( ) ) {
2020-05-14 16:41:43 +02:00
if ( cache . font . is_null ( ) ) { // avoid a strange case that may corrupt stuff
2017-05-20 17:38:03 +02:00
update_cache ( ) ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2020-09-03 13:22:16 +02:00
bool rtl = is_layout_rtl ( ) ;
2017-05-20 17:38:03 +02:00
if ( ! b - > is_pressed ( ) ) {
2021-08-13 23:31:57 +02:00
if ( b - > get_button_index ( ) = = MouseButton : : LEFT ) {
2020-09-03 13:22:16 +02:00
Point2 pos = b - > get_position ( ) ;
if ( rtl ) {
pos . x = get_size ( ) . width - pos . x ;
}
pos - = cache . bg - > get_offset ( ) ;
2017-05-20 17:38:03 +02:00
if ( show_column_titles ) {
pos . y - = _get_title_button_height ( ) ;
2017-05-17 12:55:55 +02:00
2017-05-20 17:38:03 +02:00
if ( pos . y < 0 ) {
pos . x + = cache . offset . x ;
int len = 0 ;
for ( int i = 0 ; i < columns . size ( ) ; i + + ) {
len + = get_column_width ( i ) ;
if ( pos . x < len ) {
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " column_title_pressed " ) , i ) ;
2017-05-20 17:38:03 +02:00
break ;
2017-05-17 12:55:55 +02:00
}
}
}
2017-05-20 17:38:03 +02:00
}
2017-05-17 12:55:55 +02:00
2017-05-20 17:38:03 +02:00
if ( single_select_defer ) {
select_single_item ( single_select_defer , root , single_select_defer_column ) ;
2020-04-02 01:20:12 +02:00
single_select_defer = nullptr ;
2017-05-20 17:38:03 +02:00
}
2016-05-11 16:46:08 +02:00
2017-05-20 17:38:03 +02:00
range_click_timer - > stop ( ) ;
2015-12-08 19:04:56 +01:00
2017-05-20 17:38:03 +02:00
if ( pressing_for_editor ) {
if ( range_drag_enabled ) {
range_drag_enabled = false ;
2020-04-28 15:19:37 +02:00
Input : : get_singleton ( ) - > set_mouse_mode ( Input : : MOUSE_MODE_VISIBLE ) ;
2017-05-20 17:38:03 +02:00
warp_mouse ( range_drag_capture_pos ) ;
} else {
Rect2 rect = get_selected ( ) - > get_meta ( " __focus_rect " ) ;
2020-09-03 13:22:16 +02:00
Point2 mpos = b - > get_position ( ) ;
if ( rtl ) {
mpos . x = get_size ( ) . width - mpos . x ;
}
if ( rect . has_point ( mpos ) ) {
2019-09-13 21:14:12 +02:00
if ( ! edit_selected ( ) ) {
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " item_double_clicked " ) ) ;
2019-09-13 21:14:12 +02:00
}
2016-07-28 21:37:52 +02:00
} else {
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " item_double_clicked " ) ) ;
2016-07-28 21:37:52 +02:00
}
2015-08-29 06:43:21 +02:00
}
2017-05-20 17:38:03 +02:00
pressing_for_editor = false ;
}
2015-08-29 06:43:21 +02:00
2020-04-02 01:20:12 +02:00
if ( cache . click_type = = Cache : : CLICK_BUTTON & & cache . click_item ! = nullptr ) {
2017-05-20 17:38:03 +02:00
// make sure in case of wrong reference after reconstructing whole TreeItems
2017-09-10 15:37:49 +02:00
cache . click_item = get_item_at_position ( cache . click_pos ) ;
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " button_pressed " ) , cache . click_item , cache . click_column , cache . click_id ) ;
2017-05-20 17:38:03 +02:00
}
cache . click_type = Cache : : CLICK_NONE ;
cache . click_index = - 1 ;
cache . click_id = - 1 ;
2020-04-02 01:20:12 +02:00
cache . click_item = nullptr ;
2017-05-20 17:38:03 +02:00
cache . click_column = 0 ;
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
if ( drag_touching ) {
if ( drag_speed = = 0 ) {
drag_touching_deaccel = false ;
drag_touching = false ;
2018-04-11 09:28:14 +02:00
set_physics_process_internal ( false ) ;
2017-05-20 17:38:03 +02:00
} else {
drag_touching_deaccel = true ;
2014-02-10 02:10:30 +01:00
}
}
2017-05-20 17:38:03 +02:00
update ( ) ;
2014-02-10 02:10:30 +01:00
}
2017-05-20 17:38:03 +02:00
return ;
}
2014-02-10 02:10:30 +01:00
2020-05-14 16:41:43 +02:00
if ( range_drag_enabled ) {
2017-05-20 17:38:03 +02:00
return ;
2020-05-14 16:41:43 +02:00
}
2015-08-31 00:37:23 +02:00
2017-05-20 17:38:03 +02:00
switch ( b - > get_button_index ( ) ) {
2021-08-13 23:31:57 +02:00
case MouseButton : : RIGHT :
case MouseButton : : LEFT : {
2017-05-20 17:38:03 +02:00
Ref < StyleBox > bg = cache . bg ;
2020-09-03 13:22:16 +02:00
Point2 pos = b - > get_position ( ) ;
if ( rtl ) {
pos . x = get_size ( ) . width - pos . x ;
}
pos - = bg - > get_offset ( ) ;
2017-05-20 17:38:03 +02:00
cache . click_type = Cache : : CLICK_NONE ;
2017-08-26 18:55:43 +02:00
if ( show_column_titles ) {
2017-05-20 17:38:03 +02:00
pos . y - = _get_title_button_height ( ) ;
if ( pos . y < 0 ) {
2021-08-13 23:31:57 +02:00
if ( b - > get_button_index ( ) = = MouseButton : : LEFT ) {
2017-08-26 18:55:43 +02:00
pos . x + = cache . offset . x ;
int len = 0 ;
for ( int i = 0 ; i < columns . size ( ) ; i + + ) {
len + = get_column_width ( i ) ;
if ( pos . x < len ) {
cache . click_type = Cache : : CLICK_TITLE ;
cache . click_index = i ;
//cache.click_id=;
update ( ) ;
break ;
}
2014-02-10 02:10:30 +01:00
}
2016-05-16 17:23:40 +02:00
}
2014-02-10 02:10:30 +01:00
break ;
2016-05-16 17:23:40 +02:00
}
2017-05-20 17:38:03 +02:00
}
2021-03-07 21:07:30 +01:00
if ( ! root | | ( ! root - > get_first_child ( ) & & hide_root ) ) {
2021-08-13 23:31:57 +02:00
if ( b - > get_button_index ( ) = = MouseButton : : RIGHT & & allow_rmb_select ) {
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " empty_tree_rmb_selected " ) , get_local_mouse_position ( ) ) ;
2017-05-20 17:38:03 +02:00
}
break ;
}
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
click_handled = false ;
pressing_for_editor = false ;
2019-01-14 21:20:33 +01:00
propagate_mouse_activated = false ;
2014-02-10 02:10:30 +01:00
2021-07-04 05:13:28 +02:00
int x_limit = get_size ( ) . width - cache . bg - > get_minimum_size ( ) . width ;
if ( h_scroll - > is_visible ( ) ) {
x_limit - = h_scroll - > get_minimum_size ( ) . width ;
}
cache . rtl = is_layout_rtl ( ) ;
2017-05-20 17:38:03 +02:00
blocked + + ;
2021-07-04 05:13:28 +02:00
propagate_mouse_event ( pos + cache . offset , 0 , 0 , x_limit + cache . offset . width , b - > is_double_click ( ) , root , b - > get_button_index ( ) , b ) ;
2017-05-20 17:38:03 +02:00
blocked - - ;
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
if ( pressing_for_editor ) {
2017-06-03 10:54:24 +02:00
pressing_pos = b - > get_position ( ) ;
2020-09-03 13:22:16 +02:00
if ( rtl ) {
pressing_pos . x = get_size ( ) . width - pressing_pos . x ;
}
2017-05-20 17:38:03 +02:00
}
2014-02-10 02:10:30 +01:00
2021-08-13 23:31:57 +02:00
if ( b - > get_button_index ( ) = = MouseButton : : RIGHT ) {
2017-05-20 17:38:03 +02:00
break ;
2020-05-14 16:41:43 +02:00
}
2016-05-16 04:41:48 +02:00
2017-05-20 17:38:03 +02:00
if ( drag_touching ) {
2018-04-11 09:28:14 +02:00
set_physics_process_internal ( false ) ;
2017-05-20 17:38:03 +02:00
drag_touching_deaccel = false ;
drag_touching = false ;
drag_speed = 0 ;
drag_from = 0 ;
}
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
if ( ! click_handled ) {
drag_speed = 0 ;
drag_accum = 0 ;
//last_drag_accum=0;
drag_from = v_scroll - > get_value ( ) ;
2021-06-01 14:46:17 +02:00
drag_touching = DisplayServer : : get_singleton ( ) - > screen_is_touchscreen ( DisplayServer : : get_singleton ( ) - > window_get_current_screen ( get_viewport ( ) - > get_window_id ( ) ) ) ;
2017-05-20 17:38:03 +02:00
drag_touching_deaccel = false ;
if ( drag_touching ) {
2018-04-11 09:28:14 +02:00
set_physics_process_internal ( true ) ;
2014-02-10 02:10:30 +01:00
}
2017-11-27 16:58:28 +01:00
2021-08-13 23:31:57 +02:00
if ( b - > get_button_index ( ) = = MouseButton : : LEFT ) {
2021-04-24 22:33:50 +02:00
if ( get_item_at_position ( b - > get_position ( ) ) = = nullptr & & ! b - > is_shift_pressed ( ) & & ! b - > is_ctrl_pressed ( ) & & ! b - > is_command_pressed ( ) ) {
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " nothing_selected " ) ) ;
2020-05-14 16:41:43 +02:00
}
2017-11-27 16:58:28 +01:00
}
2017-05-20 17:38:03 +02:00
}
2014-02-10 02:10:30 +01:00
2019-01-14 21:20:33 +01:00
if ( propagate_mouse_activated ) {
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " item_activated " ) ) ;
2019-01-14 21:20:33 +01:00
propagate_mouse_activated = false ;
}
2017-05-20 17:38:03 +02:00
} break ;
2021-08-13 23:31:57 +02:00
case MouseButton : : WHEEL_UP : {
2019-10-02 12:34:04 +02:00
double prev_value = v_scroll - > get_value ( ) ;
2017-05-20 17:38:03 +02:00
v_scroll - > set_value ( v_scroll - > get_value ( ) - v_scroll - > get_page ( ) * b - > get_factor ( ) / 8 ) ;
2019-10-02 12:34:04 +02:00
if ( v_scroll - > get_value ( ) ! = prev_value ) {
accept_event ( ) ;
}
2017-05-20 17:38:03 +02:00
} break ;
2021-08-13 23:31:57 +02:00
case MouseButton : : WHEEL_DOWN : {
2019-10-02 12:34:04 +02:00
double prev_value = v_scroll - > get_value ( ) ;
2017-05-20 17:38:03 +02:00
v_scroll - > set_value ( v_scroll - > get_value ( ) + v_scroll - > get_page ( ) * b - > get_factor ( ) / 8 ) ;
2019-10-02 12:34:04 +02:00
if ( v_scroll - > get_value ( ) ! = prev_value ) {
accept_event ( ) ;
}
2017-05-20 17:38:03 +02:00
} break ;
2021-03-25 21:56:12 +01:00
default :
break ;
2017-05-20 17:38:03 +02:00
}
2014-02-10 02:10:30 +01:00
}
2017-11-01 21:49:39 +01:00
Ref < InputEventPanGesture > pan_gesture = p_event ;
if ( pan_gesture . is_valid ( ) ) {
2020-01-03 11:29:22 +01:00
double prev_v = v_scroll - > get_value ( ) ;
2017-11-01 21:49:39 +01:00
v_scroll - > set_value ( v_scroll - > get_value ( ) + v_scroll - > get_page ( ) * pan_gesture - > get_delta ( ) . y / 8 ) ;
2020-01-03 11:29:22 +01:00
double prev_h = h_scroll - > get_value ( ) ;
2020-09-03 13:22:16 +02:00
if ( is_layout_rtl ( ) ) {
h_scroll - > set_value ( h_scroll - > get_value ( ) + h_scroll - > get_page ( ) * - pan_gesture - > get_delta ( ) . x / 8 ) ;
} else {
h_scroll - > set_value ( h_scroll - > get_value ( ) + h_scroll - > get_page ( ) * pan_gesture - > get_delta ( ) . x / 8 ) ;
}
2020-01-03 11:29:22 +01:00
if ( v_scroll - > get_value ( ) ! = prev_v | | h_scroll - > get_value ( ) ! = prev_h ) {
2019-10-02 12:34:04 +02:00
accept_event ( ) ;
}
2017-11-01 21:49:39 +01:00
}
2014-02-10 02:10:30 +01:00
}
bool Tree : : edit_selected ( ) {
TreeItem * s = get_selected ( ) ;
2019-08-08 22:11:48 +02:00
ERR_FAIL_COND_V_MSG ( ! s , false , " No item selected. " ) ;
2014-02-10 02:10:30 +01:00
ensure_cursor_is_visible ( ) ;
int col = get_selected_column ( ) ;
2019-08-08 22:11:48 +02:00
ERR_FAIL_INDEX_V_MSG ( col , columns . size ( ) , false , " No item column selected. " ) ;
2014-02-10 02:10:30 +01:00
2020-05-14 16:41:43 +02:00
if ( ! s - > cells [ col ] . editable ) {
2014-02-10 02:10:30 +01:00
return false ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2016-08-20 18:00:25 +02:00
Rect2 rect = s - > get_meta ( " __focus_rect " ) ;
2017-03-05 16:44:50 +01:00
popup_edited_item = s ;
popup_edited_item_col = col ;
2014-02-10 02:10:30 +01:00
2018-07-25 03:11:03 +02:00
const TreeItem : : Cell & c = s - > cells [ col ] ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
if ( c . mode = = TreeItem : : CELL_MODE_CHECK ) {
2015-11-05 16:20:45 +01:00
s - > set_checked ( col , ! c . checked ) ;
2017-03-05 16:44:50 +01:00
item_edited ( col , s ) ;
2015-11-05 16:20:45 +01:00
return true ;
2017-03-05 16:44:50 +01:00
} else if ( c . mode = = TreeItem : : CELL_MODE_CUSTOM ) {
edited_item = s ;
edited_col = col ;
2017-06-04 00:25:13 +02:00
custom_popup_rect = Rect2i ( get_global_position ( ) + rect . position , rect . size ) ;
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " custom_popup_edited " ) , false ) ;
2017-03-05 16:44:50 +01:00
item_edited ( col , s ) ;
2014-02-10 02:10:30 +01:00
return true ;
2021-12-09 10:42:46 +01:00
} else if ( c . mode = = TreeItem : : CELL_MODE_RANGE & & ! c . text . is_empty ( ) ) {
2014-02-10 02:10:30 +01:00
popup_menu - > clear ( ) ;
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < c . text . get_slice_count ( " , " ) ; i + + ) {
2019-02-12 21:10:08 +01:00
String s2 = c . text . get_slicec ( ' , ' , i ) ;
2020-12-15 13:04:21 +01:00
popup_menu - > add_item ( s2 . get_slicec ( ' : ' , 0 ) , s2 . get_slicec ( ' : ' , 1 ) . is_empty ( ) ? i : s2 . get_slicec ( ' : ' , 1 ) . to_int ( ) ) ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
popup_menu - > set_size ( Size2 ( rect . size . width , 0 ) ) ;
2021-08-31 17:43:35 +02:00
popup_menu - > set_position ( get_screen_position ( ) + rect . position + Point2i ( 0 , rect . size . height ) ) ;
2014-02-10 02:10:30 +01:00
popup_menu - > popup ( ) ;
2017-03-05 16:44:50 +01:00
popup_edited_item = s ;
popup_edited_item_col = col ;
2014-02-10 02:10:30 +01:00
return true ;
2018-09-22 22:31:56 +02:00
} else if ( c . mode = = TreeItem : : CELL_MODE_STRING | | c . mode = = TreeItem : : CELL_MODE_RANGE ) {
2020-03-20 03:32:09 +01:00
Rect2 popup_rect ;
2017-09-03 05:56:25 +02:00
Vector2 ofs ( 0 , ( text_editor - > get_size ( ) . height - rect . size . height ) / 2 ) ;
2020-03-20 03:32:09 +01:00
Point2i textedpos = get_screen_position ( ) + rect . position - ofs ;
2018-10-04 19:33:34 +02:00
cache . text_editor_position = textedpos ;
2020-03-20 03:32:09 +01:00
popup_rect . position = textedpos ;
popup_rect . size = rect . size ;
2014-02-10 02:10:30 +01:00
text_editor - > clear ( ) ;
2019-07-23 17:27:55 +02:00
text_editor - > set_text ( c . mode = = TreeItem : : CELL_MODE_STRING ? c . text : String : : num ( c . val , Math : : range_step_decimals ( c . step ) ) ) ;
2014-02-10 02:10:30 +01:00
text_editor - > select_all ( ) ;
2018-09-22 22:31:56 +02:00
if ( c . mode = = TreeItem : : CELL_MODE_RANGE ) {
2020-03-20 03:32:09 +01:00
popup_rect . size . y + = value_editor - > get_minimum_size ( ) . height ;
2020-03-14 17:06:39 +01:00
value_editor - > show ( ) ;
2017-03-05 16:44:50 +01:00
updating_value_editor = true ;
value_editor - > set_min ( c . min ) ;
value_editor - > set_max ( c . max ) ;
value_editor - > set_step ( c . step ) ;
value_editor - > set_value ( c . val ) ;
value_editor - > set_exp_ratio ( c . expr ) ;
updating_value_editor = false ;
2020-03-20 03:32:09 +01:00
} else {
value_editor - > hide ( ) ;
2014-02-10 02:10:30 +01:00
}
2020-03-20 03:32:09 +01:00
popup_editor - > set_position ( popup_rect . position ) ;
popup_editor - > set_size ( popup_rect . size ) ;
popup_editor - > popup ( ) ;
popup_editor - > child_controls_changed ( ) ;
2014-02-10 02:10:30 +01:00
text_editor - > grab_focus ( ) ;
2020-03-20 03:32:09 +01:00
2014-02-10 02:10:30 +01:00
return true ;
}
return false ;
}
2020-12-31 08:43:03 +01:00
bool Tree : : is_editing ( ) {
return popup_editor - > is_visible ( ) ;
}
2014-02-10 02:10:30 +01:00
Size2 Tree : : get_internal_min_size ( ) const {
2017-03-05 16:44:50 +01:00
Size2i size = cache . bg - > get_offset ( ) ;
2020-05-14 16:41:43 +02:00
if ( root ) {
2017-03-05 16:44:50 +01:00
size . height + = get_item_height ( root ) ;
2020-05-14 16:41:43 +02:00
}
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < columns . size ( ) ; i + + ) {
2021-06-28 15:40:56 +02:00
size . width + = get_column_minimum_width ( i ) ;
2014-02-10 02:10:30 +01:00
}
2015-08-31 00:37:23 +02:00
2014-02-10 02:10:30 +01:00
return size ;
}
void Tree : : update_scrollbars ( ) {
Size2 size = get_size ( ) ;
int tbh ;
if ( show_column_titles ) {
2017-03-05 16:44:50 +01:00
tbh = _get_title_button_height ( ) ;
2014-02-10 02:10:30 +01:00
} else {
2017-03-05 16:44:50 +01:00
tbh = 0 ;
2014-02-10 02:10:30 +01:00
}
Size2 hmin = h_scroll - > get_combined_minimum_size ( ) ;
Size2 vmin = v_scroll - > get_combined_minimum_size ( ) ;
2020-12-22 17:24:29 +01:00
v_scroll - > set_begin ( Point2 ( size . width - vmin . width , cache . bg - > get_margin ( SIDE_TOP ) ) ) ;
v_scroll - > set_end ( Point2 ( size . width , size . height - cache . bg - > get_margin ( SIDE_TOP ) - cache . bg - > get_margin ( SIDE_BOTTOM ) ) ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
h_scroll - > set_begin ( Point2 ( 0 , size . height - hmin . height ) ) ;
h_scroll - > set_end ( Point2 ( size . width - vmin . width , size . height ) ) ;
2015-08-31 00:37:23 +02:00
2021-06-25 21:19:46 +02:00
Size2 internal_min_size = get_internal_min_size ( ) ;
2015-08-31 00:37:23 +02:00
2021-06-25 21:19:46 +02:00
bool display_vscroll = internal_min_size . height + cache . bg - > get_margin ( SIDE_TOP ) > size . height ;
bool display_hscroll = internal_min_size . width + cache . bg - > get_margin ( SIDE_LEFT ) > size . width ;
for ( int i = 0 ; i < 2 ; i + + ) {
// Check twice, as both values are dependent on each other.
if ( display_hscroll ) {
display_vscroll = internal_min_size . height + cache . bg - > get_margin ( SIDE_TOP ) + hmin . height > size . height ;
}
if ( display_vscroll ) {
display_hscroll = internal_min_size . width + cache . bg - > get_margin ( SIDE_LEFT ) + vmin . width > size . width ;
}
}
if ( display_vscroll ) {
2014-02-10 02:10:30 +01:00
v_scroll - > show ( ) ;
2021-06-25 21:19:46 +02:00
v_scroll - > set_max ( internal_min_size . height ) ;
2014-02-10 02:10:30 +01:00
v_scroll - > set_page ( size . height - hmin . height - tbh ) ;
2017-03-05 16:44:50 +01:00
cache . offset . y = v_scroll - > get_value ( ) ;
2021-06-25 21:19:46 +02:00
} else {
v_scroll - > hide ( ) ;
cache . offset . y = 0 ;
2014-02-10 02:10:30 +01:00
}
2015-08-31 00:37:23 +02:00
2021-06-25 21:19:46 +02:00
if ( display_hscroll ) {
2014-02-10 02:10:30 +01:00
h_scroll - > show ( ) ;
2021-06-25 21:19:46 +02:00
h_scroll - > set_max ( internal_min_size . width ) ;
2014-02-10 02:10:30 +01:00
h_scroll - > set_page ( size . width - vmin . width ) ;
2017-03-05 16:44:50 +01:00
cache . offset . x = h_scroll - > get_value ( ) ;
2021-06-25 21:19:46 +02:00
} else {
h_scroll - > hide ( ) ;
cache . offset . x = 0 ;
2015-08-31 00:37:23 +02:00
}
2014-02-10 02:10:30 +01:00
}
int Tree : : _get_title_button_height ( ) const {
2018-01-06 19:48:54 +01:00
ERR_FAIL_COND_V ( cache . font . is_null ( ) | | cache . title_button . is_null ( ) , 0 ) ;
2020-09-03 13:22:16 +02:00
int h = 0 ;
if ( show_column_titles ) {
for ( int i = 0 ; i < columns . size ( ) ; i + + ) {
h = MAX ( h , columns [ i ] . text_buf - > get_size ( ) . y + cache . title_button - > get_minimum_size ( ) . height ) ;
}
}
return h ;
2014-02-10 02:10:30 +01:00
}
void Tree : : _notification ( int p_what ) {
2017-03-05 16:44:50 +01:00
if ( p_what = = NOTIFICATION_FOCUS_ENTER ) {
2021-10-23 10:38:52 +02:00
if ( get_viewport ( ) ) {
focus_in_id = get_viewport ( ) - > get_processed_events_count ( ) ;
}
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
if ( p_what = = NOTIFICATION_MOUSE_EXIT ) {
if ( cache . hover_type ! = Cache : : CLICK_NONE ) {
cache . hover_type = Cache : : CLICK_NONE ;
2014-02-10 02:10:30 +01:00
update ( ) ;
}
}
2017-03-05 16:44:50 +01:00
if ( p_what = = NOTIFICATION_VISIBILITY_CHANGED ) {
drag_touching = false ;
2015-08-24 01:15:56 +02:00
}
2017-03-05 16:44:50 +01:00
if ( p_what = = NOTIFICATION_ENTER_TREE ) {
2017-01-14 18:03:38 +01:00
update_cache ( ) ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
if ( p_what = = NOTIFICATION_DRAG_END ) {
drop_mode_flags = 0 ;
2016-09-17 21:29:55 +02:00
scrolling = false ;
2018-04-11 09:28:14 +02:00
set_physics_process_internal ( false ) ;
2016-05-11 16:46:08 +02:00
update ( ) ;
}
2017-03-05 16:44:50 +01:00
if ( p_what = = NOTIFICATION_DRAG_BEGIN ) {
2020-04-02 01:20:12 +02:00
single_select_defer = nullptr ;
2018-12-29 15:41:31 +01:00
if ( cache . scroll_speed > 0 ) {
2016-09-17 21:29:55 +02:00
scrolling = true ;
2018-04-11 09:28:14 +02:00
set_physics_process_internal ( true ) ;
2016-09-17 21:29:55 +02:00
}
2016-05-11 16:46:08 +02:00
}
2018-04-11 09:28:14 +02:00
if ( p_what = = NOTIFICATION_INTERNAL_PHYSICS_PROCESS ) {
2017-03-05 16:44:50 +01:00
if ( drag_touching ) {
2014-02-10 02:10:30 +01:00
if ( drag_touching_deaccel ) {
2017-01-04 05:16:14 +01:00
float pos = v_scroll - > get_value ( ) ;
2017-09-30 16:19:07 +02:00
pos + = drag_speed * get_physics_process_delta_time ( ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
bool turnoff = false ;
if ( pos < 0 ) {
pos = 0 ;
turnoff = true ;
2018-04-11 09:28:14 +02:00
set_physics_process_internal ( false ) ;
2017-03-05 16:44:50 +01:00
drag_touching = false ;
drag_touching_deaccel = false ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
if ( pos > ( v_scroll - > get_max ( ) - v_scroll - > get_page ( ) ) ) {
pos = v_scroll - > get_max ( ) - v_scroll - > get_page ( ) ;
turnoff = true ;
2014-02-10 02:10:30 +01:00
}
2017-01-04 05:16:14 +01:00
v_scroll - > set_value ( pos ) ;
2017-03-05 16:44:50 +01:00
float sgn = drag_speed < 0 ? - 1 : 1 ;
2014-02-10 02:10:30 +01:00
float val = Math : : abs ( drag_speed ) ;
2017-09-30 16:19:07 +02:00
val - = 1000 * get_physics_process_delta_time ( ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
if ( val < 0 ) {
turnoff = true ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
drag_speed = sgn * val ;
2014-02-10 02:10:30 +01:00
if ( turnoff ) {
2018-04-11 09:28:14 +02:00
set_physics_process_internal ( false ) ;
2017-03-05 16:44:50 +01:00
drag_touching = false ;
drag_touching_deaccel = false ;
2014-02-10 02:10:30 +01:00
}
}
}
2017-03-05 16:44:50 +01:00
2018-12-29 15:41:31 +01:00
Point2 mouse_position = get_viewport ( ) - > get_mouse_position ( ) - get_global_position ( ) ;
if ( scrolling & & get_rect ( ) . grow ( cache . scroll_border ) . has_point ( mouse_position ) ) {
Point2 point ;
if ( ( ABS ( mouse_position . x ) < ABS ( mouse_position . x - get_size ( ) . width ) ) & & ( ABS ( mouse_position . x ) < cache . scroll_border ) ) {
point . x = mouse_position . x - cache . scroll_border ;
} else if ( ABS ( mouse_position . x - get_size ( ) . width ) < cache . scroll_border ) {
point . x = mouse_position . x - ( get_size ( ) . width - cache . scroll_border ) ;
2016-09-17 21:29:55 +02:00
}
2018-12-29 15:41:31 +01:00
if ( ( ABS ( mouse_position . y ) < ABS ( mouse_position . y - get_size ( ) . height ) ) & & ( ABS ( mouse_position . y ) < cache . scroll_border ) ) {
point . y = mouse_position . y - cache . scroll_border ;
} else if ( ABS ( mouse_position . y - get_size ( ) . height ) < cache . scroll_border ) {
point . y = mouse_position . y - ( get_size ( ) . height - cache . scroll_border ) ;
2016-09-17 21:29:55 +02:00
}
2018-12-29 15:41:31 +01:00
2017-09-30 16:19:07 +02:00
point * = cache . scroll_speed * get_physics_process_delta_time ( ) ;
2016-09-17 21:29:55 +02:00
point + = get_scroll ( ) ;
2017-01-04 05:16:14 +01:00
h_scroll - > set_value ( point . x ) ;
v_scroll - > set_value ( point . y ) ;
2016-09-17 21:29:55 +02:00
}
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
if ( p_what = = NOTIFICATION_DRAW ) {
2014-02-10 02:10:30 +01:00
update_cache ( ) ;
update_scrollbars ( ) ;
2015-08-31 00:37:23 +02:00
RID ci = get_canvas_item ( ) ;
2014-02-10 02:10:30 +01:00
Ref < StyleBox > bg = cache . bg ;
2021-07-17 23:22:52 +02:00
Color font_outline_color = get_theme_color ( SNAME ( " font_outline_color " ) ) ;
int outline_size = get_theme_constant ( SNAME ( " outline_size " ) ) ;
2015-08-31 00:37:23 +02:00
2014-02-10 02:10:30 +01:00
Point2 draw_ofs ;
2017-03-05 16:44:50 +01:00
draw_ofs + = bg - > get_offset ( ) ;
Size2 draw_size = get_size ( ) - bg - > get_minimum_size ( ) ;
2021-07-04 05:13:28 +02:00
if ( h_scroll - > is_visible ( ) ) {
draw_size . width - = h_scroll - > get_minimum_size ( ) . width ;
}
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
bg - > draw ( ci , Rect2 ( Point2 ( ) , get_size ( ) ) ) ;
2014-02-10 02:10:30 +01:00
int tbh = _get_title_button_height ( ) ;
2017-03-05 16:44:50 +01:00
draw_ofs . y + = tbh ;
draw_size . y - = tbh ;
2014-02-10 02:10:30 +01:00
2021-07-04 05:13:28 +02:00
cache . rtl = is_layout_rtl ( ) ;
2021-06-28 15:40:56 +02:00
if ( root & & get_size ( ) . x > 0 & & get_size ( ) . y > 0 ) {
2017-03-05 16:44:50 +01:00
draw_item ( Point2 ( ) , draw_ofs , draw_size , root ) ;
2014-02-10 02:10:30 +01:00
}
if ( show_column_titles ) {
2018-10-13 12:34:57 +02:00
//title buttons
2020-12-22 17:24:29 +01:00
int ofs2 = cache . bg - > get_margin ( SIDE_LEFT ) ;
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < columns . size ( ) ; i + + ) {
Ref < StyleBox > sb = ( cache . click_type = = Cache : : CLICK_TITLE & & cache . click_index = = i ) ? cache . title_button_pressed : ( ( cache . hover_type = = Cache : : CLICK_TITLE & & cache . hover_index = = i ) ? cache . title_button_hover : cache . title_button ) ;
2014-02-10 02:10:30 +01:00
Ref < Font > f = cache . tb_font ;
2020-12-22 17:24:29 +01:00
Rect2 tbrect = Rect2 ( ofs2 - cache . offset . x , bg - > get_margin ( SIDE_TOP ) , get_column_width ( i ) , tbh ) ;
2021-07-04 05:13:28 +02:00
if ( cache . rtl ) {
2020-09-03 13:22:16 +02:00
tbrect . position . x = get_size ( ) . width - tbrect . size . x - tbrect . position . x ;
}
2017-03-05 16:44:50 +01:00
sb - > draw ( ci , tbrect ) ;
2019-02-12 21:10:08 +01:00
ofs2 + = tbrect . size . width ;
2014-02-10 02:10:30 +01:00
//text
int clip_w = tbrect . size . width - sb - > get_minimum_size ( ) . width ;
2020-09-03 13:22:16 +02:00
columns . write [ i ] . text_buf - > set_width ( clip_w ) ;
2020-12-25 22:45:28 +01:00
Vector2 text_pos = tbrect . position + Point2i ( sb - > get_offset ( ) . x + ( tbrect . size . width - columns [ i ] . text_buf - > get_size ( ) . x ) / 2 , ( tbrect . size . height - columns [ i ] . text_buf - > get_size ( ) . y ) / 2 ) ;
if ( outline_size > 0 & & font_outline_color . a > 0 ) {
columns [ i ] . text_buf - > draw_outline ( ci , text_pos , outline_size , font_outline_color ) ;
}
columns [ i ] . text_buf - > draw ( ci , text_pos , cache . title_button_color ) ;
2014-02-10 02:10:30 +01:00
}
}
2021-05-09 12:41:47 +02:00
// Draw the background focus outline last, so that it is drawn in front of the section headings.
// Otherwise, section heading backgrounds can appear to be in front of the focus outline when scrolling.
if ( has_focus ( ) ) {
RenderingServer : : get_singleton ( ) - > canvas_item_add_clip_ignore ( ci , true ) ;
2021-07-17 23:22:52 +02:00
const Ref < StyleBox > bg_focus = get_theme_stylebox ( SNAME ( " bg_focus " ) ) ;
2021-05-09 12:41:47 +02:00
bg_focus - > draw ( ci , Rect2 ( Point2 ( ) , get_size ( ) ) ) ;
RenderingServer : : get_singleton ( ) - > canvas_item_add_clip_ignore ( ci , false ) ;
}
2014-02-10 02:10:30 +01:00
}
2020-09-03 13:22:16 +02:00
if ( p_what = = NOTIFICATION_THEME_CHANGED | | p_what = = NOTIFICATION_LAYOUT_DIRECTION_CHANGED | | p_what = = NOTIFICATION_TRANSLATION_CHANGED ) {
2015-01-22 15:07:16 +01:00
update_cache ( ) ;
2020-09-03 13:22:16 +02:00
_update_all ( ) ;
2015-01-22 15:07:16 +01:00
}
2018-10-04 19:33:34 +02:00
if ( p_what = = NOTIFICATION_RESIZED | | p_what = = NOTIFICATION_TRANSFORM_CHANGED ) {
2020-04-02 01:20:12 +02:00
if ( popup_edited_item ! = nullptr ) {
2018-10-04 19:33:34 +02:00
Rect2 rect = popup_edited_item - > get_meta ( " __focus_rect " ) ;
Vector2 ofs ( 0 , ( text_editor - > get_size ( ) . height - rect . size . height ) / 2 ) ;
Point2i textedpos = get_global_position ( ) + rect . position - ofs ;
if ( cache . text_editor_position ! = textedpos ) {
cache . text_editor_position = textedpos ;
text_editor - > set_position ( textedpos ) ;
value_editor - > set_position ( textedpos + Point2i ( 0 , text_editor - > get_size ( ) . height ) ) ;
}
}
}
2014-02-10 02:10:30 +01:00
}
2020-09-03 13:22:16 +02:00
void Tree : : _update_all ( ) {
for ( int i = 0 ; i < columns . size ( ) ; i + + ) {
update_column ( i ) ;
}
if ( root ) {
update_item_cache ( root ) ;
}
}
2014-02-10 02:10:30 +01:00
Size2 Tree : : get_minimum_size ( ) const {
2021-06-25 21:19:46 +02:00
if ( h_scroll_enabled & & v_scroll_enabled ) {
return Size2 ( ) ;
} else {
Vector2 min_size = get_internal_min_size ( ) ;
Ref < StyleBox > bg = cache . bg ;
if ( bg . is_valid ( ) ) {
min_size . x + = bg - > get_margin ( SIDE_LEFT ) + bg - > get_margin ( SIDE_RIGHT ) ;
min_size . y + = bg - > get_margin ( SIDE_TOP ) + bg - > get_margin ( SIDE_BOTTOM ) ;
}
return Vector2 ( h_scroll_enabled ? 0 : min_size . x , v_scroll_enabled ? 0 : min_size . y ) ;
}
2014-02-10 02:10:30 +01:00
}
2017-12-14 22:13:48 +01:00
TreeItem * Tree : : create_item ( TreeItem * p_parent , int p_idx ) {
2020-04-02 01:20:12 +02:00
ERR_FAIL_COND_V ( blocked > 0 , nullptr ) ;
2014-02-10 02:10:30 +01:00
2020-04-02 01:20:12 +02:00
TreeItem * ti = nullptr ;
2014-02-10 02:10:30 +01:00
if ( p_parent ) {
2021-03-07 21:07:30 +01:00
ERR_FAIL_COND_V_MSG ( p_parent - > tree ! = this , nullptr , " A different tree owns the given parent " ) ;
ti = p_parent - > create_child ( p_idx ) ;
2014-02-10 02:10:30 +01:00
} else {
2017-12-14 22:13:48 +01:00
if ( ! root ) {
// No root exists, make the given item the new root.
ti = memnew ( TreeItem ( this ) ) ;
2020-04-02 01:20:12 +02:00
ERR_FAIL_COND_V ( ! ti , nullptr ) ;
2017-12-14 22:13:48 +01:00
ti - > cells . resize ( columns . size ( ) ) ;
2021-03-07 21:07:30 +01:00
ti - > is_root = true ;
2017-12-14 22:13:48 +01:00
root = ti ;
} else {
// Root exists, append or insert to root.
ti = create_item ( root , p_idx ) ;
}
2014-02-10 02:10:30 +01:00
}
return ti ;
}
2021-06-28 15:40:56 +02:00
TreeItem * Tree : : get_root ( ) const {
2014-02-10 02:10:30 +01:00
return root ;
}
2020-05-14 14:29:06 +02:00
2021-06-28 15:40:56 +02:00
TreeItem * Tree : : get_last_item ( ) const {
2017-03-05 16:44:50 +01:00
TreeItem * last = root ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
while ( last ) {
2020-05-14 16:41:43 +02:00
if ( last - > next ) {
2017-03-05 16:44:50 +01:00
last = last - > next ;
2021-03-07 21:07:30 +01:00
} else if ( last - > first_child ) {
last = last - > first_child ;
2020-05-14 16:41:43 +02:00
} else {
2014-02-10 02:10:30 +01:00
break ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
}
return last ;
}
2017-08-10 21:02:19 +02:00
void Tree : : item_edited ( int p_column , TreeItem * p_item , bool p_lmb ) {
2017-03-05 16:44:50 +01:00
edited_item = p_item ;
edited_col = p_column ;
2020-09-03 13:22:16 +02:00
if ( p_item ! = nullptr & & p_column > = 0 & & p_column < p_item - > cells . size ( ) ) {
edited_item - > cells . write [ p_column ] . dirty = true ;
}
2020-05-14 16:41:43 +02:00
if ( p_lmb ) {
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " item_edited " ) ) ;
2020-05-14 16:41:43 +02:00
} else {
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " item_rmb_edited " ) ) ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
void Tree : : item_changed ( int p_column , TreeItem * p_item ) {
2020-09-03 13:22:16 +02:00
if ( p_item ! = nullptr & & p_column > = 0 & & p_column < p_item - > cells . size ( ) ) {
p_item - > cells . write [ p_column ] . dirty = true ;
}
2015-08-31 00:37:23 +02:00
update ( ) ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
void Tree : : item_selected ( int p_column , TreeItem * p_item ) {
if ( select_mode = = SELECT_MULTI ) {
2020-05-14 16:41:43 +02:00
if ( ! p_item - > cells [ p_column ] . selectable ) {
2014-02-10 02:10:30 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2018-07-25 03:11:03 +02:00
p_item - > cells . write [ p_column ] . selected = true ;
2021-07-17 23:22:52 +02:00
//emit_signal(SNAME("multi_selected"),p_item,p_column,true); - NO this is for TreeItem::select
2014-02-10 02:10:30 +01:00
2018-01-13 17:27:32 +01:00
selected_col = p_column ;
2021-02-16 01:36:16 +01:00
if ( ! selected_item ) {
selected_item = p_item ;
}
2014-02-10 02:10:30 +01:00
} else {
2017-03-05 16:44:50 +01:00
select_single_item ( p_item , root , p_column ) ;
2014-02-10 02:10:30 +01:00
}
update ( ) ;
}
2017-03-05 16:44:50 +01:00
void Tree : : item_deselected ( int p_column , TreeItem * p_item ) {
2021-02-07 22:11:27 +01:00
if ( selected_item = = p_item ) {
selected_item = nullptr ;
2021-03-03 19:39:29 +01:00
if ( selected_col = = p_column ) {
selected_col = - 1 ;
}
2021-02-07 22:11:27 +01:00
}
2017-03-05 16:44:50 +01:00
if ( select_mode = = SELECT_MULTI | | select_mode = = SELECT_SINGLE ) {
2018-07-25 03:11:03 +02:00
p_item - > cells . write [ p_column ] . selected = false ;
2015-08-31 00:37:23 +02:00
}
2014-02-10 02:10:30 +01:00
update ( ) ;
}
void Tree : : set_select_mode ( SelectMode p_mode ) {
2017-03-05 16:44:50 +01:00
select_mode = p_mode ;
2014-02-10 02:10:30 +01:00
}
2018-01-11 23:35:12 +01:00
Tree : : SelectMode Tree : : get_select_mode ( ) const {
return select_mode ;
}
2017-11-27 16:58:28 +01:00
void Tree : : deselect_all ( ) {
TreeItem * item = get_next_selected ( get_root ( ) ) ;
while ( item ) {
item - > deselect ( selected_col ) ;
2018-01-13 17:27:32 +01:00
TreeItem * prev_item = item ;
2017-11-27 16:58:28 +01:00
item = get_next_selected ( get_root ( ) ) ;
2018-01-13 17:27:32 +01:00
ERR_FAIL_COND ( item = = prev_item ) ;
2017-11-27 16:58:28 +01:00
}
2020-04-02 01:20:12 +02:00
selected_item = nullptr ;
2017-11-27 16:58:28 +01:00
selected_col = - 1 ;
update ( ) ;
}
bool Tree : : is_anything_selected ( ) {
2020-04-02 01:20:12 +02:00
return ( selected_item ! = nullptr ) ;
2017-11-27 16:58:28 +01:00
}
2014-02-10 02:10:30 +01:00
void Tree : : clear ( ) {
2019-06-20 16:59:48 +02:00
ERR_FAIL_COND ( blocked > 0 ) ;
2014-02-10 02:10:30 +01:00
2016-03-18 00:10:09 +01:00
if ( pressing_for_editor ) {
if ( range_drag_enabled ) {
range_drag_enabled = false ;
2020-04-28 15:19:37 +02:00
Input : : get_singleton ( ) - > set_mouse_mode ( Input : : MOUSE_MODE_VISIBLE ) ;
2016-03-18 00:10:09 +01:00
warp_mouse ( range_drag_capture_pos ) ;
}
pressing_for_editor = false ;
}
2014-02-10 02:10:30 +01:00
if ( root ) {
2017-03-05 16:44:50 +01:00
memdelete ( root ) ;
2020-04-02 01:20:12 +02:00
root = nullptr ;
2014-02-10 02:10:30 +01:00
} ;
2020-04-02 01:20:12 +02:00
selected_item = nullptr ;
edited_item = nullptr ;
popup_edited_item = nullptr ;
2014-02-10 02:10:30 +01:00
update ( ) ;
} ;
void Tree : : set_hide_root ( bool p_enabled ) {
2017-03-05 16:44:50 +01:00
hide_root = p_enabled ;
2015-08-31 00:37:23 +02:00
update ( ) ;
2014-02-10 02:10:30 +01:00
}
2018-01-11 23:35:12 +01:00
bool Tree : : is_root_hidden ( ) const {
return hide_root ;
}
2021-06-28 15:40:56 +02:00
void Tree : : set_column_custom_minimum_width ( int p_column , int p_min_width ) {
2017-03-05 16:44:50 +01:00
ERR_FAIL_INDEX ( p_column , columns . size ( ) ) ;
2014-02-10 02:10:30 +01:00
2021-06-28 15:40:56 +02:00
if ( p_min_width < 0 ) {
2014-02-10 02:10:30 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2021-06-28 15:40:56 +02:00
columns . write [ p_column ] . custom_min_width = p_min_width ;
2014-02-10 02:10:30 +01:00
update ( ) ;
}
2020-05-14 14:29:06 +02:00
2017-03-05 16:44:50 +01:00
void Tree : : set_column_expand ( int p_column , bool p_expand ) {
ERR_FAIL_INDEX ( p_column , columns . size ( ) ) ;
2015-08-31 00:37:23 +02:00
2018-07-25 03:11:03 +02:00
columns . write [ p_column ] . expand = p_expand ;
2014-02-10 02:10:30 +01:00
update ( ) ;
}
2021-07-04 05:13:28 +02:00
void Tree : : set_column_expand_ratio ( int p_column , int p_ratio ) {
ERR_FAIL_INDEX ( p_column , columns . size ( ) ) ;
columns . write [ p_column ] . expand_ratio = p_ratio ;
update ( ) ;
}
void Tree : : set_column_clip_content ( int p_column , bool p_fit ) {
ERR_FAIL_INDEX ( p_column , columns . size ( ) ) ;
columns . write [ p_column ] . clip_content = p_fit ;
update ( ) ;
}
bool Tree : : is_column_expanding ( int p_column ) const {
ERR_FAIL_INDEX_V ( p_column , columns . size ( ) , false ) ;
return columns [ p_column ] . expand ;
}
int Tree : : get_column_expand_ratio ( int p_column ) const {
ERR_FAIL_INDEX_V ( p_column , columns . size ( ) , 1 ) ;
return columns [ p_column ] . expand_ratio ;
}
bool Tree : : is_column_clipping_content ( int p_column ) const {
ERR_FAIL_INDEX_V ( p_column , columns . size ( ) , false ) ;
return columns [ p_column ] . clip_content ;
}
2014-02-10 02:10:30 +01:00
TreeItem * Tree : : get_selected ( ) const {
return selected_item ;
}
int Tree : : get_selected_column ( ) const {
return selected_col ;
}
TreeItem * Tree : : get_edited ( ) const {
return edited_item ;
}
int Tree : : get_edited_column ( ) const {
return edited_col ;
}
2017-03-05 16:44:50 +01:00
TreeItem * Tree : : get_next_selected ( TreeItem * p_item ) {
2017-01-14 12:26:56 +01:00
/*
if ( ! p_item )
2020-04-02 01:20:12 +02:00
return nullptr ;
2017-01-14 12:26:56 +01:00
*/
2020-05-14 16:41:43 +02:00
if ( ! root ) {
2020-04-02 01:20:12 +02:00
return nullptr ;
2020-05-14 16:41:43 +02:00
}
2015-08-31 00:37:23 +02:00
2017-03-05 16:44:50 +01:00
while ( true ) {
2014-02-10 02:10:30 +01:00
if ( ! p_item ) {
2017-03-05 16:44:50 +01:00
p_item = root ;
2014-02-10 02:10:30 +01:00
} else {
2021-03-07 21:07:30 +01:00
if ( p_item - > first_child ) {
p_item = p_item - > first_child ;
2015-08-31 00:37:23 +02:00
2014-02-10 02:10:30 +01:00
} else if ( p_item - > next ) {
2017-03-05 16:44:50 +01:00
p_item = p_item - > next ;
2014-02-10 02:10:30 +01:00
} else {
2017-03-05 16:44:50 +01:00
while ( ! p_item - > next ) {
p_item = p_item - > parent ;
2020-05-14 16:41:43 +02:00
if ( p_item = = nullptr ) {
2020-04-02 01:20:12 +02:00
return nullptr ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
}
2015-08-31 00:37:23 +02:00
2017-03-05 16:44:50 +01:00
p_item = p_item - > next ;
2014-02-10 02:10:30 +01:00
}
}
2015-08-31 00:37:23 +02:00
2020-05-14 16:41:43 +02:00
for ( int i = 0 ; i < columns . size ( ) ; i + + ) {
if ( p_item - > cells [ i ] . selected ) {
2014-02-10 02:10:30 +01:00
return p_item ;
2020-05-14 16:41:43 +02:00
}
}
2014-02-10 02:10:30 +01:00
}
2015-08-31 00:37:23 +02:00
2020-04-02 01:20:12 +02:00
return nullptr ;
2014-02-10 02:10:30 +01:00
}
2021-06-28 15:40:56 +02:00
int Tree : : get_column_minimum_width ( int p_column ) const {
2017-03-05 16:44:50 +01:00
ERR_FAIL_INDEX_V ( p_column , columns . size ( ) , - 1 ) ;
2015-08-31 00:37:23 +02:00
2021-09-24 10:11:44 +02:00
// Use the custom minimum width.
2021-07-04 05:13:28 +02:00
int min_width = columns [ p_column ] . custom_min_width ;
2021-09-24 10:11:44 +02:00
// Check if the visible title of the column is wider.
2021-07-04 05:13:28 +02:00
if ( show_column_titles ) {
2021-10-25 10:49:18 +02:00
min_width = MAX ( cache . font - > get_string_size ( columns [ p_column ] . title , cache . font_size ) . width + cache . bg - > get_margin ( SIDE_LEFT ) + cache . bg - > get_margin ( SIDE_RIGHT ) , min_width ) ;
2021-07-04 05:13:28 +02:00
}
if ( ! columns [ p_column ] . clip_content ) {
2021-06-28 15:40:56 +02:00
int depth = 0 ;
TreeItem * next ;
for ( TreeItem * item = get_root ( ) ; item ; item = next ) {
next = item - > get_next_visible ( ) ;
// Compute the depth in tree.
if ( next & & p_column = = 0 ) {
if ( next - > get_parent ( ) = = item ) {
depth + = 1 ;
} else {
TreeItem * common_parent = item - > get_parent ( ) ;
while ( common_parent ! = next - > get_parent ( ) ) {
common_parent = common_parent - > get_parent ( ) ;
depth - = 1 ;
}
}
}
// Get the item minimum size.
Size2 item_size = item - > get_minimum_size ( p_column ) ;
if ( p_column = = 0 ) {
item_size . width + = cache . item_margin * depth ;
2021-09-24 10:11:44 +02:00
} else {
item_size . width + = cache . hseparation ;
2021-06-28 15:40:56 +02:00
}
2021-09-24 10:11:44 +02:00
// Check if the item is wider.
2021-06-28 15:40:56 +02:00
min_width = MAX ( min_width , item_size . width ) ;
}
2020-05-14 16:41:43 +02:00
}
2021-07-04 05:13:28 +02:00
return min_width ;
2021-06-28 15:40:56 +02:00
}
2015-08-31 00:37:23 +02:00
2021-06-28 15:40:56 +02:00
int Tree : : get_column_width ( int p_column ) const {
ERR_FAIL_INDEX_V ( p_column , columns . size ( ) , - 1 ) ;
2021-03-17 20:10:36 +01:00
2021-07-04 05:13:28 +02:00
int column_width = get_column_minimum_width ( p_column ) ;
2021-06-28 15:40:56 +02:00
if ( columns [ p_column ] . expand ) {
int expand_area = get_size ( ) . width ;
2015-08-31 00:37:23 +02:00
2021-06-28 15:40:56 +02:00
Ref < StyleBox > bg = cache . bg ;
2015-08-31 00:37:23 +02:00
2021-06-28 15:40:56 +02:00
if ( bg . is_valid ( ) ) {
expand_area - = bg - > get_margin ( SIDE_LEFT ) + bg - > get_margin ( SIDE_RIGHT ) ;
}
if ( v_scroll - > is_visible_in_tree ( ) ) {
expand_area - = v_scroll - > get_combined_minimum_size ( ) . width ;
}
2015-08-31 00:37:23 +02:00
2021-06-28 15:40:56 +02:00
int expanding_total = 0 ;
2015-08-31 00:37:23 +02:00
2021-06-28 15:40:56 +02:00
for ( int i = 0 ; i < columns . size ( ) ; i + + ) {
2021-07-04 05:13:28 +02:00
expand_area - = get_column_minimum_width ( i ) ;
if ( columns [ i ] . expand ) {
expanding_total + = columns [ i ] . expand_ratio ;
2021-06-28 15:40:56 +02:00
}
2014-02-10 02:10:30 +01:00
}
2021-07-04 05:13:28 +02:00
if ( expand_area > = expanding_total & & expanding_total > 0 ) {
column_width + = expand_area * columns [ p_column ] . expand_ratio / expanding_total ;
2021-06-28 15:40:56 +02:00
}
2021-07-04 05:13:28 +02:00
}
2015-08-31 00:37:23 +02:00
2021-07-04 05:13:28 +02:00
return column_width ;
2014-02-10 02:10:30 +01:00
}
void Tree : : propagate_set_columns ( TreeItem * p_item ) {
2017-03-05 16:44:50 +01:00
p_item - > cells . resize ( columns . size ( ) ) ;
2015-08-31 00:37:23 +02:00
2021-03-07 21:07:30 +01:00
TreeItem * c = p_item - > get_first_child ( ) ;
2017-03-05 16:44:50 +01:00
while ( c ) {
2014-02-10 02:10:30 +01:00
propagate_set_columns ( c ) ;
2020-09-03 13:22:16 +02:00
c = c - > next ;
2014-02-10 02:10:30 +01:00
}
}
void Tree : : set_columns ( int p_columns ) {
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND ( p_columns < 1 ) ;
ERR_FAIL_COND ( blocked > 0 ) ;
2014-02-10 02:10:30 +01:00
columns . resize ( p_columns ) ;
2015-08-31 00:37:23 +02:00
2020-05-14 16:41:43 +02:00
if ( root ) {
2014-02-10 02:10:30 +01:00
propagate_set_columns ( root ) ;
2020-05-14 16:41:43 +02:00
}
if ( selected_col > = p_columns ) {
2017-03-05 16:44:50 +01:00
selected_col = p_columns - 1 ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
update ( ) ;
}
int Tree : : get_columns ( ) const {
return columns . size ( ) ;
}
void Tree : : _scroll_moved ( float ) {
update ( ) ;
}
Rect2 Tree : : get_custom_popup_rect ( ) const {
return custom_popup_rect ;
}
int Tree : : get_item_offset ( TreeItem * p_item ) const {
2017-03-05 16:44:50 +01:00
TreeItem * it = root ;
int ofs = _get_title_button_height ( ) ;
2020-05-14 16:41:43 +02:00
if ( ! it ) {
2014-02-10 02:10:30 +01:00
return 0 ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
while ( true ) {
2020-05-14 16:41:43 +02:00
if ( it = = p_item ) {
2014-02-10 02:10:30 +01:00
return ofs ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2020-01-02 02:20:43 +01:00
ofs + = compute_item_height ( it ) ;
if ( it ! = root | | ! hide_root ) {
ofs + = cache . vseparation ;
}
2014-02-10 02:10:30 +01:00
2021-03-07 21:07:30 +01:00
if ( it - > first_child & & ! it - > collapsed ) {
it = it - > first_child ;
2014-02-10 02:10:30 +01:00
} else if ( it - > next ) {
2017-03-05 16:44:50 +01:00
it = it - > next ;
2014-02-10 02:10:30 +01:00
} else {
2017-03-05 16:44:50 +01:00
while ( ! it - > next ) {
it = it - > parent ;
2020-05-14 16:41:43 +02:00
if ( it = = nullptr ) {
2014-02-10 02:10:30 +01:00
return 0 ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
it = it - > next ;
2014-02-10 02:10:30 +01:00
}
}
return - 1 ; //not found
}
void Tree : : ensure_cursor_is_visible ( ) {
2020-01-03 11:29:22 +01:00
if ( ! is_inside_tree ( ) ) {
2014-02-10 02:10:30 +01:00
return ;
2020-01-03 11:29:22 +01:00
}
if ( ! selected_item | | ( selected_col = = - 1 ) ) {
return ; // Nothing under cursor.
}
2014-02-10 02:10:30 +01:00
2020-01-03 11:29:22 +01:00
const Size2 area_size = get_size ( ) - cache . bg - > get_minimum_size ( ) ;
2020-01-01 15:20:12 +01:00
2020-01-03 11:29:22 +01:00
int y_offset = get_item_offset ( selected_item ) ;
if ( y_offset ! = - 1 ) {
const int tbh = _get_title_button_height ( ) ;
y_offset - = tbh ;
2020-01-01 15:20:12 +01:00
2020-01-03 11:29:22 +01:00
const int cell_h = compute_item_height ( selected_item ) + cache . vseparation ;
const int screen_h = area_size . height - h_scroll - > get_combined_minimum_size ( ) . height - tbh ;
2014-02-10 02:10:30 +01:00
2020-01-03 11:29:22 +01:00
if ( cell_h > screen_h ) { // Screen size is too small, maybe it was not resized yet.
v_scroll - > set_value ( y_offset ) ;
} else if ( y_offset + cell_h > v_scroll - > get_value ( ) + screen_h ) {
2021-07-17 23:22:52 +02:00
v_scroll - > call_deferred ( SNAME ( " set_value " ) , y_offset - screen_h + cell_h ) ;
2020-01-03 11:29:22 +01:00
} else if ( y_offset < v_scroll - > get_value ( ) ) {
v_scroll - > set_value ( y_offset ) ;
}
}
if ( select_mode ! = SELECT_ROW ) { // Cursor always at col 0 in this mode.
int x_offset = 0 ;
for ( int i = 0 ; i < selected_col ; i + + ) {
x_offset + = get_column_width ( i ) ;
}
const int cell_w = get_column_width ( selected_col ) ;
const int screen_w = area_size . width - v_scroll - > get_combined_minimum_size ( ) . width ;
if ( cell_w > screen_w ) {
h_scroll - > set_value ( x_offset ) ;
} else if ( x_offset + cell_w > h_scroll - > get_value ( ) + screen_w ) {
2021-07-17 23:22:52 +02:00
h_scroll - > call_deferred ( SNAME ( " set_value " ) , x_offset - screen_w + cell_w ) ;
2020-01-03 11:29:22 +01:00
} else if ( x_offset < h_scroll - > get_value ( ) ) {
h_scroll - > set_value ( x_offset ) ;
}
2019-04-12 04:21:48 +02:00
}
2014-02-10 02:10:30 +01:00
}
int Tree : : get_pressed_button ( ) const {
return pressed_button ;
}
2017-03-05 16:44:50 +01:00
Rect2 Tree : : get_item_rect ( TreeItem * p_item , int p_column ) const {
ERR_FAIL_NULL_V ( p_item , Rect2 ( ) ) ;
ERR_FAIL_COND_V ( p_item - > tree ! = this , Rect2 ( ) ) ;
if ( p_column ! = - 1 ) {
ERR_FAIL_INDEX_V ( p_column , columns . size ( ) , Rect2 ( ) ) ;
2014-02-10 02:10:30 +01:00
}
int ofs = get_item_offset ( p_item ) ;
int height = compute_item_height ( p_item ) ;
Rect2 r ;
2017-06-04 00:25:13 +02:00
r . position . y = ofs ;
2017-03-05 16:44:50 +01:00
r . size . height = height ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
if ( p_column = = - 1 ) {
2017-06-04 00:25:13 +02:00
r . position . x = 0 ;
2017-03-05 16:44:50 +01:00
r . size . x = get_size ( ) . width ;
2014-02-10 02:10:30 +01:00
} else {
2017-03-05 16:44:50 +01:00
int accum = 0 ;
for ( int i = 0 ; i < p_column ; i + + ) {
accum + = get_column_width ( i ) ;
2014-02-10 02:10:30 +01:00
}
2017-06-04 00:25:13 +02:00
r . position . x = accum ;
2017-03-05 16:44:50 +01:00
r . size . x = get_column_width ( p_column ) ;
2014-02-10 02:10:30 +01:00
}
return r ;
}
void Tree : : set_column_titles_visible ( bool p_show ) {
2017-03-05 16:44:50 +01:00
show_column_titles = p_show ;
2014-02-10 02:10:30 +01:00
update ( ) ;
}
bool Tree : : are_column_titles_visible ( ) const {
return show_column_titles ;
}
2017-03-05 16:44:50 +01:00
void Tree : : set_column_title ( int p_column , const String & p_title ) {
ERR_FAIL_INDEX ( p_column , columns . size ( ) ) ;
2020-09-03 13:22:16 +02:00
if ( cache . font . is_null ( ) ) { // avoid a strange case that may corrupt stuff
update_cache ( ) ;
}
2018-07-25 03:11:03 +02:00
columns . write [ p_column ] . title = p_title ;
2020-09-03 13:22:16 +02:00
update_column ( p_column ) ;
2014-02-10 02:10:30 +01:00
update ( ) ;
}
String Tree : : get_column_title ( int p_column ) const {
2017-03-05 16:44:50 +01:00
ERR_FAIL_INDEX_V ( p_column , columns . size ( ) , " " ) ;
2014-02-10 02:10:30 +01:00
return columns [ p_column ] . title ;
}
2020-09-03 13:22:16 +02:00
void Tree : : set_column_title_direction ( int p_column , Control : : TextDirection p_text_direction ) {
ERR_FAIL_INDEX ( p_column , columns . size ( ) ) ;
ERR_FAIL_COND ( ( int ) p_text_direction < - 1 | | ( int ) p_text_direction > 3 ) ;
if ( columns [ p_column ] . text_direction ! = p_text_direction ) {
columns . write [ p_column ] . text_direction = p_text_direction ;
update_column ( p_column ) ;
update ( ) ;
}
}
Control : : TextDirection Tree : : get_column_title_direction ( int p_column ) const {
ERR_FAIL_INDEX_V ( p_column , columns . size ( ) , TEXT_DIRECTION_INHERITED ) ;
return columns [ p_column ] . text_direction ;
}
void Tree : : clear_column_title_opentype_features ( int p_column ) {
ERR_FAIL_INDEX ( p_column , columns . size ( ) ) ;
columns . write [ p_column ] . opentype_features . clear ( ) ;
update_column ( p_column ) ;
update ( ) ;
}
void Tree : : set_column_title_opentype_feature ( int p_column , const String & p_name , int p_value ) {
ERR_FAIL_INDEX ( p_column , columns . size ( ) ) ;
int32_t tag = TS - > name_to_tag ( p_name ) ;
if ( ! columns [ p_column ] . opentype_features . has ( tag ) | | ( int ) columns [ p_column ] . opentype_features [ tag ] ! = p_value ) {
columns . write [ p_column ] . opentype_features [ tag ] = p_value ;
update_column ( p_column ) ;
update ( ) ;
}
}
int Tree : : get_column_title_opentype_feature ( int p_column , const String & p_name ) const {
ERR_FAIL_INDEX_V ( p_column , columns . size ( ) , - 1 ) ;
int32_t tag = TS - > name_to_tag ( p_name ) ;
if ( ! columns [ p_column ] . opentype_features . has ( tag ) ) {
return - 1 ;
}
return columns [ p_column ] . opentype_features [ tag ] ;
}
void Tree : : set_column_title_language ( int p_column , const String & p_language ) {
ERR_FAIL_INDEX ( p_column , columns . size ( ) ) ;
if ( columns [ p_column ] . language ! = p_language ) {
columns . write [ p_column ] . language = p_language ;
update_column ( p_column ) ;
update ( ) ;
}
}
String Tree : : get_column_title_language ( int p_column ) const {
ERR_FAIL_INDEX_V ( p_column , columns . size ( ) , " " ) ;
return columns [ p_column ] . language ;
}
2014-02-10 02:10:30 +01:00
Point2 Tree : : get_scroll ( ) const {
Point2 ofs ;
2020-05-14 16:41:43 +02:00
if ( h_scroll - > is_visible_in_tree ( ) ) {
2017-03-05 16:44:50 +01:00
ofs . x = h_scroll - > get_value ( ) ;
2020-05-14 16:41:43 +02:00
}
if ( v_scroll - > is_visible_in_tree ( ) ) {
2017-03-05 16:44:50 +01:00
ofs . y = v_scroll - > get_value ( ) ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
return ofs ;
}
2017-11-04 20:21:41 +01:00
void Tree : : scroll_to_item ( TreeItem * p_item ) {
if ( ! is_visible_in_tree ( ) ) {
// hack to work around crash in get_item_rect() if Tree is not in tree.
return ;
}
// make sure the scrollbar min and max are up to date with latest changes.
update_scrollbars ( ) ;
const Rect2 r = get_item_rect ( p_item ) ;
2020-06-30 23:22:26 +02:00
if ( r . position . y < = v_scroll - > get_value ( ) ) {
2017-11-04 20:21:41 +01:00
v_scroll - > set_value ( r . position . y ) ;
} else if ( r . position . y + r . size . y + 2 * cache . vseparation > v_scroll - > get_value ( ) + get_size ( ) . y ) {
v_scroll - > set_value ( r . position . y + r . size . y + 2 * cache . vseparation - get_size ( ) . y ) ;
}
}
2021-06-25 21:19:46 +02:00
void Tree : : set_h_scroll_enabled ( bool p_enable ) {
h_scroll_enabled = p_enable ;
2021-12-06 14:02:34 +01:00
update_minimum_size ( ) ;
2021-06-25 21:19:46 +02:00
}
bool Tree : : is_h_scroll_enabled ( ) const {
return h_scroll_enabled ;
}
void Tree : : set_v_scroll_enabled ( bool p_enable ) {
v_scroll_enabled = p_enable ;
2021-12-06 14:02:34 +01:00
update_minimum_size ( ) ;
2021-06-25 21:19:46 +02:00
}
bool Tree : : is_v_scroll_enabled ( ) const {
return v_scroll_enabled ;
}
2017-03-05 16:44:50 +01:00
TreeItem * Tree : : _search_item_text ( TreeItem * p_at , const String & p_find , int * r_col , bool p_selectable , bool p_backwards ) {
2019-05-11 18:32:53 +02:00
TreeItem * from = p_at ;
2020-07-20 00:53:46 +02:00
TreeItem * loop = nullptr ; // Safe-guard against infinite loop.
2017-03-05 16:44:50 +01:00
while ( p_at ) {
for ( int i = 0 ; i < columns . size ( ) ; i + + ) {
if ( p_at - > get_text ( i ) . findn ( p_find ) = = 0 & & ( ! p_selectable | | p_at - > is_selectable ( i ) ) ) {
2020-05-14 16:41:43 +02:00
if ( r_col ) {
2017-03-05 16:44:50 +01:00
* r_col = i ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
return p_at ;
}
}
2020-05-14 16:41:43 +02:00
if ( p_backwards ) {
2019-05-11 18:32:53 +02:00
p_at = p_at - > get_prev_visible ( true ) ;
2020-05-14 16:41:43 +02:00
} else {
2019-05-11 18:32:53 +02:00
p_at = p_at - > get_next_visible ( true ) ;
2020-05-14 16:41:43 +02:00
}
2019-05-11 18:32:53 +02:00
2020-05-14 16:41:43 +02:00
if ( ( p_at ) = = from ) {
2019-05-11 18:32:53 +02:00
break ;
2020-05-14 16:41:43 +02:00
}
2020-07-20 00:53:46 +02:00
if ( ! loop ) {
loop = p_at ;
} else if ( loop = = p_at ) {
break ;
}
2014-02-10 02:10:30 +01:00
}
2020-04-02 01:20:12 +02:00
return nullptr ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
TreeItem * Tree : : search_item_text ( const String & p_find , int * r_col , bool p_selectable ) {
2019-06-04 01:50:50 +02:00
TreeItem * from = get_selected ( ) ;
2019-05-11 18:32:53 +02:00
2020-05-14 16:41:43 +02:00
if ( ! from ) {
2019-05-11 18:32:53 +02:00
from = root ;
2020-05-14 16:41:43 +02:00
}
if ( ! from ) {
2020-04-02 01:20:12 +02:00
return nullptr ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2019-06-04 01:50:50 +02:00
return _search_item_text ( from - > get_next_visible ( true ) , p_find , r_col , p_selectable ) ;
2014-02-10 02:10:30 +01:00
}
2020-02-02 04:07:01 +01:00
TreeItem * Tree : : get_item_with_text ( const String & p_find ) const {
for ( TreeItem * current = root ; current ; current = current - > get_next_visible ( ) ) {
for ( int i = 0 ; i < columns . size ( ) ; i + + ) {
if ( current - > get_text ( i ) = = p_find ) {
return current ;
}
}
}
2020-04-02 01:20:12 +02:00
return nullptr ;
2020-02-02 04:07:01 +01:00
}
2017-03-05 16:44:50 +01:00
void Tree : : _do_incr_search ( const String & p_add ) {
2014-02-10 02:10:30 +01:00
uint64_t time = OS : : get_singleton ( ) - > get_ticks_usec ( ) / 1000 ; // convert to msec
uint64_t diff = time - last_keypress ;
2020-05-14 16:41:43 +02:00
if ( diff > uint64_t ( GLOBAL_DEF ( " gui/timers/incremental_search_max_interval_msec " , 2000 ) ) ) {
2017-03-05 16:44:50 +01:00
incr_search = p_add ;
2020-05-14 16:41:43 +02:00
} else if ( incr_search ! = p_add ) {
2017-03-05 16:44:50 +01:00
incr_search + = p_add ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
last_keypress = time ;
2014-02-10 02:10:30 +01:00
int col ;
2017-03-05 16:44:50 +01:00
TreeItem * item = search_item_text ( incr_search , & col , true ) ;
2020-05-14 16:41:43 +02:00
if ( ! item ) {
2014-02-10 02:10:30 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
item - > select ( col ) ;
ensure_cursor_is_visible ( ) ;
}
2017-03-05 16:44:50 +01:00
TreeItem * Tree : : _find_item_at_pos ( TreeItem * p_item , const Point2 & p_pos , int & r_column , int & h , int & section ) const {
2014-02-10 02:10:30 +01:00
Point2 pos = p_pos ;
2017-03-05 16:44:50 +01:00
if ( root ! = p_item | | ! hide_root ) {
h = compute_item_height ( p_item ) + cache . vseparation ;
if ( pos . y < h ) {
if ( drop_mode_flags = = DROP_MODE_ON_ITEM ) {
section = 0 ;
} else if ( drop_mode_flags = = DROP_MODE_INBETWEEN ) {
section = pos . y < h / 2 ? - 1 : 1 ;
} else if ( pos . y < h / 4 ) {
section = - 1 ;
} else if ( pos . y > = ( h * 3 / 4 ) ) {
section = 1 ;
2016-05-11 16:46:08 +02:00
} else {
2017-03-05 16:44:50 +01:00
section = 0 ;
2016-05-11 16:46:08 +02:00
}
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < columns . size ( ) ; i + + ) {
2014-02-10 02:10:30 +01:00
int w = get_column_width ( i ) ;
if ( pos . x < w ) {
2017-03-05 16:44:50 +01:00
r_column = i ;
2016-05-11 16:46:08 +02:00
2014-02-10 02:10:30 +01:00
return p_item ;
}
2017-03-05 16:44:50 +01:00
pos . x - = w ;
2014-02-10 02:10:30 +01:00
}
2016-05-11 16:46:08 +02:00
2020-04-02 01:20:12 +02:00
return nullptr ;
2014-02-10 02:10:30 +01:00
} else {
2017-03-05 16:44:50 +01:00
pos . y - = h ;
2014-02-10 02:10:30 +01:00
}
} else {
2017-03-05 16:44:50 +01:00
h = 0 ;
2014-02-10 02:10:30 +01:00
}
2020-05-14 16:41:43 +02:00
if ( p_item - > is_collapsed ( ) ) {
2020-04-02 01:20:12 +02:00
return nullptr ; // do not try children, it's collapsed
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2021-03-07 21:07:30 +01:00
TreeItem * n = p_item - > get_first_child ( ) ;
2017-03-05 16:44:50 +01:00
while ( n ) {
2014-02-10 02:10:30 +01:00
int ch ;
2017-03-05 16:44:50 +01:00
TreeItem * r = _find_item_at_pos ( n , pos , r_column , ch , section ) ;
pos . y - = ch ;
h + = ch ;
2020-05-14 16:41:43 +02:00
if ( r ) {
2014-02-10 02:10:30 +01:00
return r ;
2020-05-14 16:41:43 +02:00
}
2017-03-05 16:44:50 +01:00
n = n - > get_next ( ) ;
2014-02-10 02:10:30 +01:00
}
2020-04-02 01:20:12 +02:00
return nullptr ;
2014-02-10 02:10:30 +01:00
}
2017-09-10 15:37:49 +02:00
int Tree : : get_column_at_position ( const Point2 & p_pos ) const {
2016-05-11 16:46:08 +02:00
if ( root ) {
2017-03-05 16:44:50 +01:00
Point2 pos = p_pos ;
2020-09-03 13:22:16 +02:00
if ( is_layout_rtl ( ) ) {
pos . x = get_size ( ) . width - pos . x ;
}
2016-05-11 16:46:08 +02:00
pos - = cache . bg - > get_offset ( ) ;
2017-03-05 16:44:50 +01:00
pos . y - = _get_title_button_height ( ) ;
2020-05-14 16:41:43 +02:00
if ( pos . y < 0 ) {
2016-05-11 16:46:08 +02:00
return - 1 ;
2020-05-14 16:41:43 +02:00
}
2016-05-11 16:46:08 +02:00
2020-05-14 16:41:43 +02:00
if ( h_scroll - > is_visible_in_tree ( ) ) {
2017-03-05 16:44:50 +01:00
pos . x + = h_scroll - > get_value ( ) ;
2020-05-14 16:41:43 +02:00
}
if ( v_scroll - > is_visible_in_tree ( ) ) {
2017-03-05 16:44:50 +01:00
pos . y + = v_scroll - > get_value ( ) ;
2020-05-14 16:41:43 +02:00
}
2016-05-11 16:46:08 +02:00
2017-03-05 16:44:50 +01:00
int col , h , section ;
TreeItem * it = _find_item_at_pos ( root , pos , col , h , section ) ;
2016-05-11 16:46:08 +02:00
if ( it ) {
return col ;
}
}
return - 1 ;
}
2017-09-10 15:37:49 +02:00
int Tree : : get_drop_section_at_position ( const Point2 & p_pos ) const {
2016-05-11 16:46:08 +02:00
if ( root ) {
2017-03-05 16:44:50 +01:00
Point2 pos = p_pos ;
2020-09-03 13:22:16 +02:00
if ( is_layout_rtl ( ) ) {
pos . x = get_size ( ) . width - pos . x ;
}
2016-05-11 16:46:08 +02:00
pos - = cache . bg - > get_offset ( ) ;
2017-03-05 16:44:50 +01:00
pos . y - = _get_title_button_height ( ) ;
2020-05-14 16:41:43 +02:00
if ( pos . y < 0 ) {
2016-05-11 16:46:08 +02:00
return - 100 ;
2020-05-14 16:41:43 +02:00
}
2016-05-11 16:46:08 +02:00
2020-05-14 16:41:43 +02:00
if ( h_scroll - > is_visible_in_tree ( ) ) {
2017-03-05 16:44:50 +01:00
pos . x + = h_scroll - > get_value ( ) ;
2020-05-14 16:41:43 +02:00
}
if ( v_scroll - > is_visible_in_tree ( ) ) {
2017-03-05 16:44:50 +01:00
pos . y + = v_scroll - > get_value ( ) ;
2020-05-14 16:41:43 +02:00
}
2016-05-11 16:46:08 +02:00
2017-03-05 16:44:50 +01:00
int col , h , section ;
TreeItem * it = _find_item_at_pos ( root , pos , col , h , section ) ;
2016-05-11 16:46:08 +02:00
if ( it ) {
return section ;
}
}
return - 100 ;
}
2020-05-14 14:29:06 +02:00
2017-09-10 15:37:49 +02:00
TreeItem * Tree : : get_item_at_position ( const Point2 & p_pos ) const {
2016-05-11 16:46:08 +02:00
if ( root ) {
2017-03-05 16:44:50 +01:00
Point2 pos = p_pos ;
2020-09-03 13:22:16 +02:00
if ( is_layout_rtl ( ) ) {
pos . x = get_size ( ) . width - pos . x ;
}
2016-05-11 16:46:08 +02:00
pos - = cache . bg - > get_offset ( ) ;
2017-03-05 16:44:50 +01:00
pos . y - = _get_title_button_height ( ) ;
2020-05-14 16:41:43 +02:00
if ( pos . y < 0 ) {
2020-04-02 01:20:12 +02:00
return nullptr ;
2020-05-14 16:41:43 +02:00
}
2016-05-11 16:46:08 +02:00
2020-05-14 16:41:43 +02:00
if ( h_scroll - > is_visible_in_tree ( ) ) {
2017-03-05 16:44:50 +01:00
pos . x + = h_scroll - > get_value ( ) ;
2020-05-14 16:41:43 +02:00
}
if ( v_scroll - > is_visible_in_tree ( ) ) {
2017-03-05 16:44:50 +01:00
pos . y + = v_scroll - > get_value ( ) ;
2020-05-14 16:41:43 +02:00
}
2016-05-11 16:46:08 +02:00
2017-03-05 16:44:50 +01:00
int col , h , section ;
TreeItem * it = _find_item_at_pos ( root , pos , col , h , section ) ;
2016-05-11 16:46:08 +02:00
if ( it ) {
return it ;
}
}
2020-04-02 01:20:12 +02:00
return nullptr ;
2016-05-11 16:46:08 +02:00
}
2019-12-13 06:13:47 +01:00
int Tree : : get_button_id_at_position ( const Point2 & p_pos ) const {
if ( root ) {
Point2 pos = p_pos ;
pos - = cache . bg - > get_offset ( ) ;
pos . y - = _get_title_button_height ( ) ;
if ( pos . y < 0 ) {
return - 1 ;
}
if ( h_scroll - > is_visible_in_tree ( ) ) {
pos . x + = h_scroll - > get_value ( ) ;
}
if ( v_scroll - > is_visible_in_tree ( ) ) {
pos . y + = v_scroll - > get_value ( ) ;
}
int col , h , section ;
TreeItem * it = _find_item_at_pos ( root , pos , col , h , section ) ;
if ( it ) {
const TreeItem : : Cell & c = it - > cells [ col ] ;
int col_width = get_column_width ( col ) ;
for ( int i = 0 ; i < col ; i + + ) {
pos . x - = get_column_width ( i ) ;
}
for ( int j = c . buttons . size ( ) - 1 ; j > = 0 ; j - - ) {
Ref < Texture2D > b = c . buttons [ j ] . texture ;
Size2 size = b - > get_size ( ) + cache . button_pressed - > get_minimum_size ( ) ;
if ( pos . x > col_width - size . width ) {
return c . buttons [ j ] . id ;
}
col_width - = size . width ;
}
}
}
return - 1 ;
}
2017-03-05 16:44:50 +01:00
String Tree : : get_tooltip ( const Point2 & p_pos ) const {
2014-02-10 02:10:30 +01:00
if ( root ) {
2017-03-05 16:44:50 +01:00
Point2 pos = p_pos ;
2014-02-10 02:10:30 +01:00
pos - = cache . bg - > get_offset ( ) ;
2017-03-05 16:44:50 +01:00
pos . y - = _get_title_button_height ( ) ;
2020-05-14 16:41:43 +02:00
if ( pos . y < 0 ) {
2014-02-10 02:10:30 +01:00
return Control : : get_tooltip ( p_pos ) ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2020-05-14 16:41:43 +02:00
if ( h_scroll - > is_visible_in_tree ( ) ) {
2017-03-05 16:44:50 +01:00
pos . x + = h_scroll - > get_value ( ) ;
2020-05-14 16:41:43 +02:00
}
if ( v_scroll - > is_visible_in_tree ( ) ) {
2017-03-05 16:44:50 +01:00
pos . y + = v_scroll - > get_value ( ) ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
int col , h , section ;
TreeItem * it = _find_item_at_pos ( root , pos , col , h , section ) ;
2014-02-10 02:10:30 +01:00
2014-09-21 06:43:42 +02:00
if ( it ) {
2018-07-25 03:11:03 +02:00
const TreeItem : : Cell & c = it - > cells [ col ] ;
2017-04-24 21:41:17 +02:00
int col_width = get_column_width ( col ) ;
2019-06-10 05:33:47 +02:00
2020-05-14 16:41:43 +02:00
for ( int i = 0 ; i < col ; i + + ) {
2019-06-10 05:33:47 +02:00
pos . x - = get_column_width ( i ) ;
2020-05-14 16:41:43 +02:00
}
2019-06-10 05:33:47 +02:00
2017-04-24 21:41:17 +02:00
for ( int j = c . buttons . size ( ) - 1 ; j > = 0 ; j - - ) {
2019-06-11 20:43:37 +02:00
Ref < Texture2D > b = c . buttons [ j ] . texture ;
2017-04-24 21:41:17 +02:00
Size2 size = b - > get_size ( ) + cache . button_pressed - > get_minimum_size ( ) ;
if ( pos . x > col_width - size . width ) {
String tooltip = c . buttons [ j ] . tooltip ;
2021-12-09 10:42:46 +01:00
if ( ! tooltip . is_empty ( ) ) {
2017-04-24 21:41:17 +02:00
return tooltip ;
}
}
col_width - = size . width ;
}
2014-02-10 02:10:30 +01:00
String ret ;
2020-05-14 16:41:43 +02:00
if ( it - > get_tooltip ( col ) = = " " ) {
2017-03-05 16:44:50 +01:00
ret = it - > get_text ( col ) ;
2020-05-14 16:41:43 +02:00
} else {
2017-03-05 16:44:50 +01:00
ret = it - > get_tooltip ( col ) ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
return ret ;
}
}
return Control : : get_tooltip ( p_pos ) ;
}
void Tree : : set_cursor_can_exit_tree ( bool p_enable ) {
2017-03-05 16:44:50 +01:00
cursor_can_exit_tree = p_enable ;
2014-02-10 02:10:30 +01:00
}
2015-11-14 00:56:44 +01:00
void Tree : : set_hide_folding ( bool p_hide ) {
2017-03-05 16:44:50 +01:00
hide_folding = p_hide ;
2015-11-14 00:56:44 +01:00
update ( ) ;
}
bool Tree : : is_folding_hidden ( ) const {
return hide_folding ;
}
2016-05-11 16:46:08 +02:00
void Tree : : set_drop_mode_flags ( int p_flags ) {
2020-05-14 16:41:43 +02:00
if ( drop_mode_flags = = p_flags ) {
2016-05-12 01:57:52 +02:00
return ;
2020-05-14 16:41:43 +02:00
}
2017-03-05 16:44:50 +01:00
drop_mode_flags = p_flags ;
if ( drop_mode_flags = = 0 ) {
2020-04-02 01:20:12 +02:00
drop_mode_over = nullptr ;
2016-05-11 16:46:08 +02:00
}
update ( ) ;
}
int Tree : : get_drop_mode_flags ( ) const {
return drop_mode_flags ;
}
2017-01-21 23:00:25 +01:00
void Tree : : set_edit_checkbox_cell_only_when_checkbox_is_pressed ( bool p_enable ) {
2017-03-05 16:44:50 +01:00
force_edit_checkbox_only_on_checkbox = p_enable ;
2017-01-21 23:00:25 +01:00
}
bool Tree : : get_edit_checkbox_cell_only_when_checkbox_is_pressed ( ) const {
return force_edit_checkbox_only_on_checkbox ;
}
2016-05-16 04:41:48 +02:00
void Tree : : set_allow_rmb_select ( bool p_allow ) {
2017-03-05 16:44:50 +01:00
allow_rmb_select = p_allow ;
2016-05-16 04:41:48 +02:00
}
2017-03-05 16:44:50 +01:00
bool Tree : : get_allow_rmb_select ( ) const {
2016-05-16 04:41:48 +02:00
return allow_rmb_select ;
}
2017-08-18 23:19:12 +02:00
void Tree : : set_allow_reselect ( bool p_allow ) {
allow_reselect = p_allow ;
}
bool Tree : : get_allow_reselect ( ) const {
return allow_reselect ;
}
2014-02-10 02:10:30 +01:00
void Tree : : _bind_methods ( ) {
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " clear " ) , & Tree : : clear ) ;
2022-01-25 16:37:41 +01:00
ClassDB : : bind_method ( D_METHOD ( " create_item " , " parent " , " idx " ) , & Tree : : create_item , DEFVAL ( Variant ( ) ) , DEFVAL ( - 1 ) ) ;
2017-03-05 16:44:50 +01:00
2017-08-09 13:19:41 +02:00
ClassDB : : bind_method ( D_METHOD ( " get_root " ) , & Tree : : get_root ) ;
2021-06-28 15:40:56 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_column_custom_minimum_width " , " column " , " min_width " ) , & Tree : : set_column_custom_minimum_width ) ;
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_column_expand " , " column " , " expand " ) , & Tree : : set_column_expand ) ;
2021-07-04 05:13:28 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_column_expand_ratio " , " column " , " ratio " ) , & Tree : : set_column_expand_ratio ) ;
ClassDB : : bind_method ( D_METHOD ( " set_column_clip_content " , " column " , " enable " ) , & Tree : : set_column_clip_content ) ;
ClassDB : : bind_method ( D_METHOD ( " is_column_expanding " , " column " ) , & Tree : : is_column_expanding ) ;
ClassDB : : bind_method ( D_METHOD ( " is_column_clipping_content " , " column " ) , & Tree : : is_column_clipping_content ) ;
ClassDB : : bind_method ( D_METHOD ( " get_column_expand_ratio " , " column " ) , & Tree : : get_column_expand_ratio ) ;
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " get_column_width " , " column " ) , & Tree : : get_column_width ) ;
ClassDB : : bind_method ( D_METHOD ( " set_hide_root " , " enable " ) , & Tree : : set_hide_root ) ;
2018-01-11 23:35:12 +01:00
ClassDB : : bind_method ( D_METHOD ( " is_root_hidden " ) , & Tree : : is_root_hidden ) ;
2022-01-25 16:37:41 +01:00
ClassDB : : bind_method ( D_METHOD ( " get_next_selected " , " from " ) , & Tree : : get_next_selected ) ;
2017-08-09 13:19:41 +02:00
ClassDB : : bind_method ( D_METHOD ( " get_selected " ) , & Tree : : get_selected ) ;
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " get_selected_column " ) , & Tree : : get_selected_column ) ;
ClassDB : : bind_method ( D_METHOD ( " get_pressed_button " ) , & Tree : : get_pressed_button ) ;
ClassDB : : bind_method ( D_METHOD ( " set_select_mode " , " mode " ) , & Tree : : set_select_mode ) ;
2018-01-11 23:35:12 +01:00
ClassDB : : bind_method ( D_METHOD ( " get_select_mode " ) , & Tree : : get_select_mode ) ;
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_columns " , " amount " ) , & Tree : : set_columns ) ;
ClassDB : : bind_method ( D_METHOD ( " get_columns " ) , & Tree : : get_columns ) ;
2017-08-09 13:19:41 +02:00
ClassDB : : bind_method ( D_METHOD ( " get_edited " ) , & Tree : : get_edited ) ;
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " get_edited_column " ) , & Tree : : get_edited_column ) ;
2020-11-03 21:08:05 +01:00
ClassDB : : bind_method ( D_METHOD ( " edit_selected " ) , & Tree : : edit_selected ) ;
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " get_custom_popup_rect " ) , & Tree : : get_custom_popup_rect ) ;
2022-01-25 16:37:41 +01:00
ClassDB : : bind_method ( D_METHOD ( " get_item_area_rect " , " item " , " column " ) , & Tree : : get_item_rect , DEFVAL ( - 1 ) ) ;
2017-09-10 15:37:49 +02:00
ClassDB : : bind_method ( D_METHOD ( " get_item_at_position " , " position " ) , & Tree : : get_item_at_position ) ;
ClassDB : : bind_method ( D_METHOD ( " get_column_at_position " , " position " ) , & Tree : : get_column_at_position ) ;
ClassDB : : bind_method ( D_METHOD ( " get_drop_section_at_position " , " position " ) , & Tree : : get_drop_section_at_position ) ;
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " ensure_cursor_is_visible " ) , & Tree : : ensure_cursor_is_visible ) ;
ClassDB : : bind_method ( D_METHOD ( " set_column_titles_visible " , " visible " ) , & Tree : : set_column_titles_visible ) ;
ClassDB : : bind_method ( D_METHOD ( " are_column_titles_visible " ) , & Tree : : are_column_titles_visible ) ;
ClassDB : : bind_method ( D_METHOD ( " set_column_title " , " column " , " title " ) , & Tree : : set_column_title ) ;
ClassDB : : bind_method ( D_METHOD ( " get_column_title " , " column " ) , & Tree : : get_column_title ) ;
2020-09-03 13:22:16 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_column_title_direction " , " column " , " direction " ) , & Tree : : set_column_title_direction ) ;
ClassDB : : bind_method ( D_METHOD ( " get_column_title_direction " , " column " ) , & Tree : : get_column_title_direction ) ;
ClassDB : : bind_method ( D_METHOD ( " set_column_title_opentype_feature " , " column " , " tag " , " value " ) , & Tree : : set_column_title_opentype_feature ) ;
ClassDB : : bind_method ( D_METHOD ( " get_column_title_opentype_feature " , " column " , " tag " ) , & Tree : : get_column_title_opentype_feature ) ;
ClassDB : : bind_method ( D_METHOD ( " clear_column_title_opentype_features " , " column " ) , & Tree : : clear_column_title_opentype_features ) ;
ClassDB : : bind_method ( D_METHOD ( " set_column_title_language " , " column " , " language " ) , & Tree : : set_column_title_language ) ;
ClassDB : : bind_method ( D_METHOD ( " get_column_title_language " , " column " ) , & Tree : : get_column_title_language ) ;
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " get_scroll " ) , & Tree : : get_scroll ) ;
2022-01-25 16:37:41 +01:00
ClassDB : : bind_method ( D_METHOD ( " scroll_to_item " , " item " ) , & Tree : : scroll_to_item ) ;
2017-03-05 16:44:50 +01:00
2021-06-25 21:19:46 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_h_scroll_enabled " , " h_scroll " ) , & Tree : : set_h_scroll_enabled ) ;
ClassDB : : bind_method ( D_METHOD ( " is_h_scroll_enabled " ) , & Tree : : is_h_scroll_enabled ) ;
ClassDB : : bind_method ( D_METHOD ( " set_v_scroll_enabled " , " h_scroll " ) , & Tree : : set_v_scroll_enabled ) ;
ClassDB : : bind_method ( D_METHOD ( " is_v_scroll_enabled " ) , & Tree : : is_v_scroll_enabled ) ;
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_hide_folding " , " hide " ) , & Tree : : set_hide_folding ) ;
ClassDB : : bind_method ( D_METHOD ( " is_folding_hidden " ) , & Tree : : is_folding_hidden ) ;
ClassDB : : bind_method ( D_METHOD ( " set_drop_mode_flags " , " flags " ) , & Tree : : set_drop_mode_flags ) ;
ClassDB : : bind_method ( D_METHOD ( " get_drop_mode_flags " ) , & Tree : : get_drop_mode_flags ) ;
ClassDB : : bind_method ( D_METHOD ( " set_allow_rmb_select " , " allow " ) , & Tree : : set_allow_rmb_select ) ;
ClassDB : : bind_method ( D_METHOD ( " get_allow_rmb_select " ) , & Tree : : get_allow_rmb_select ) ;
2017-08-18 23:19:12 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_allow_reselect " , " allow " ) , & Tree : : set_allow_reselect ) ;
ClassDB : : bind_method ( D_METHOD ( " get_allow_reselect " ) , & Tree : : get_allow_reselect ) ;
2017-03-05 16:44:50 +01:00
2018-01-11 23:35:12 +01:00
ADD_PROPERTY ( PropertyInfo ( Variant : : INT , " columns " ) , " set_columns " , " get_columns " ) ;
2021-12-30 18:04:14 +01:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " column_titles_visible " ) , " set_column_titles_visible " , " are_column_titles_visible " ) ;
2018-01-11 23:35:12 +01:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " allow_reselect " ) , " set_allow_reselect " , " get_allow_reselect " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " allow_rmb_select " ) , " set_allow_rmb_select " , " get_allow_rmb_select " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " hide_folding " ) , " set_hide_folding " , " is_folding_hidden " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " hide_root " ) , " set_hide_root " , " is_root_hidden " ) ;
2021-05-22 04:30:58 +02:00
ADD_PROPERTY ( PropertyInfo ( Variant : : INT , " drop_mode_flags " , PROPERTY_HINT_FLAGS , " On Item,In Between " ) , " set_drop_mode_flags " , " get_drop_mode_flags " ) ;
2018-01-11 23:35:12 +01:00
ADD_PROPERTY ( PropertyInfo ( Variant : : INT , " select_mode " , PROPERTY_HINT_ENUM , " Single,Row,Multi " ) , " set_select_mode " , " get_select_mode " ) ;
2021-06-25 21:19:46 +02:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " scroll_horizontal_enabled " ) , " set_h_scroll_enabled " , " is_h_scroll_enabled " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " scroll_vertical_enabled " ) , " set_v_scroll_enabled " , " is_v_scroll_enabled " ) ;
2018-01-11 23:35:12 +01:00
2017-03-05 16:44:50 +01:00
ADD_SIGNAL ( MethodInfo ( " item_selected " ) ) ;
ADD_SIGNAL ( MethodInfo ( " cell_selected " ) ) ;
2018-09-01 12:05:51 +02:00
ADD_SIGNAL ( MethodInfo ( " multi_selected " , PropertyInfo ( Variant : : OBJECT , " item " , PROPERTY_HINT_RESOURCE_TYPE , " TreeItem " ) , PropertyInfo ( Variant : : INT , " column " ) , PropertyInfo ( Variant : : BOOL , " selected " ) ) ) ;
2017-09-10 15:37:49 +02:00
ADD_SIGNAL ( MethodInfo ( " item_rmb_selected " , PropertyInfo ( Variant : : VECTOR2 , " position " ) ) ) ;
2019-04-09 19:22:14 +02:00
ADD_SIGNAL ( MethodInfo ( " empty_rmb " , PropertyInfo ( Variant : : VECTOR2 , " position " ) ) ) ;
2017-09-10 15:37:49 +02:00
ADD_SIGNAL ( MethodInfo ( " empty_tree_rmb_selected " , PropertyInfo ( Variant : : VECTOR2 , " position " ) ) ) ;
2017-03-05 16:44:50 +01:00
ADD_SIGNAL ( MethodInfo ( " item_edited " ) ) ;
2017-08-10 21:02:19 +02:00
ADD_SIGNAL ( MethodInfo ( " item_rmb_edited " ) ) ;
2017-06-05 01:35:08 +02:00
ADD_SIGNAL ( MethodInfo ( " item_custom_button_pressed " ) ) ;
2017-03-05 16:44:50 +01:00
ADD_SIGNAL ( MethodInfo ( " item_double_clicked " ) ) ;
2018-09-01 12:05:51 +02:00
ADD_SIGNAL ( MethodInfo ( " item_collapsed " , PropertyInfo ( Variant : : OBJECT , " item " , PROPERTY_HINT_RESOURCE_TYPE , " TreeItem " ) ) ) ;
2021-09-17 17:50:24 +02:00
ADD_SIGNAL ( MethodInfo ( " check_propagated_to_item " , PropertyInfo ( Variant : : OBJECT , " item " , PROPERTY_HINT_RESOURCE_TYPE , " TreeItem " ) , PropertyInfo ( Variant : : INT , " column " ) ) ) ;
2021-04-13 10:25:44 +02:00
//ADD_SIGNAL( MethodInfo("item_double_clicked" ) );
2018-09-01 12:05:51 +02:00
ADD_SIGNAL ( MethodInfo ( " button_pressed " , PropertyInfo ( Variant : : OBJECT , " item " , PROPERTY_HINT_RESOURCE_TYPE , " TreeItem " ) , PropertyInfo ( Variant : : INT , " column " ) , PropertyInfo ( Variant : : INT , " id " ) ) ) ;
2017-03-05 16:44:50 +01:00
ADD_SIGNAL ( MethodInfo ( " custom_popup_edited " , PropertyInfo ( Variant : : BOOL , " arrow_clicked " ) ) ) ;
ADD_SIGNAL ( MethodInfo ( " item_activated " ) ) ;
2017-05-17 12:55:55 +02:00
ADD_SIGNAL ( MethodInfo ( " column_title_pressed " , PropertyInfo ( Variant : : INT , " column " ) ) ) ;
2017-11-26 12:49:21 +01:00
ADD_SIGNAL ( MethodInfo ( " nothing_selected " ) ) ;
2014-02-10 02:10:30 +01:00
2017-08-20 17:45:01 +02:00
BIND_ENUM_CONSTANT ( SELECT_SINGLE ) ;
BIND_ENUM_CONSTANT ( SELECT_ROW ) ;
BIND_ENUM_CONSTANT ( SELECT_MULTI ) ;
2016-05-11 16:46:08 +02:00
2017-08-20 17:45:01 +02:00
BIND_ENUM_CONSTANT ( DROP_MODE_DISABLED ) ;
BIND_ENUM_CONSTANT ( DROP_MODE_ON_ITEM ) ;
BIND_ENUM_CONSTANT ( DROP_MODE_INBETWEEN ) ;
2014-02-10 02:10:30 +01:00
}
Tree : : Tree ( ) {
columns . resize ( 1 ) ;
2017-03-05 16:44:50 +01:00
2014-02-10 02:10:30 +01:00
set_focus_mode ( FOCUS_ALL ) ;
2015-08-31 00:37:23 +02:00
2017-03-05 16:44:50 +01:00
popup_menu = memnew ( PopupMenu ) ;
2014-02-10 02:10:30 +01:00
popup_menu - > hide ( ) ;
2021-08-25 15:49:30 +02:00
add_child ( popup_menu , false , INTERNAL_MODE_FRONT ) ;
2020-03-20 03:32:09 +01:00
2020-07-01 15:59:42 +02:00
popup_editor = memnew ( Popup ) ;
2020-03-20 03:32:09 +01:00
popup_editor - > set_wrap_controls ( true ) ;
2021-08-25 15:49:30 +02:00
add_child ( popup_editor , false , INTERNAL_MODE_FRONT ) ;
2020-03-20 03:32:09 +01:00
popup_editor_vb = memnew ( VBoxContainer ) ;
popup_editor - > add_child ( popup_editor_vb ) ;
popup_editor_vb - > add_theme_constant_override ( " separation " , 0 ) ;
2020-12-22 17:24:29 +01:00
popup_editor_vb - > set_anchors_and_offsets_preset ( PRESET_WIDE ) ;
2017-03-05 16:44:50 +01:00
text_editor = memnew ( LineEdit ) ;
2020-03-20 03:32:09 +01:00
popup_editor_vb - > add_child ( text_editor ) ;
text_editor - > set_v_size_flags ( SIZE_EXPAND_FILL ) ;
text_editor - > set_h_size_flags ( SIZE_EXPAND_FILL ) ;
2017-03-05 16:44:50 +01:00
value_editor = memnew ( HSlider ) ;
2020-03-20 03:32:09 +01:00
value_editor - > set_v_size_flags ( SIZE_EXPAND_FILL ) ;
value_editor - > set_h_size_flags ( SIZE_EXPAND_FILL ) ;
popup_editor_vb - > add_child ( value_editor ) ;
2014-02-10 02:10:30 +01:00
value_editor - > hide ( ) ;
2017-03-05 16:44:50 +01:00
h_scroll = memnew ( HScrollBar ) ;
v_scroll = memnew ( VScrollBar ) ;
2015-08-31 00:37:23 +02:00
2021-08-25 15:49:30 +02:00
add_child ( h_scroll , false , INTERNAL_MODE_FRONT ) ;
add_child ( v_scroll , false , INTERNAL_MODE_FRONT ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
range_click_timer = memnew ( Timer ) ;
2020-02-21 18:28:45 +01:00
range_click_timer - > connect ( " timeout " , callable_mp ( this , & Tree : : _range_click_timeout ) ) ;
2021-08-25 15:49:30 +02:00
add_child ( range_click_timer , false , INTERNAL_MODE_FRONT ) ;
2015-12-08 19:04:56 +01:00
2020-02-21 18:28:45 +01:00
h_scroll - > connect ( " value_changed " , callable_mp ( this , & Tree : : _scroll_moved ) ) ;
v_scroll - > connect ( " value_changed " , callable_mp ( this , & Tree : : _scroll_moved ) ) ;
2021-06-16 18:43:34 +02:00
text_editor - > connect ( " text_submitted " , callable_mp ( this , & Tree : : _text_editor_submit ) ) ;
2020-03-20 03:32:09 +01:00
popup_editor - > connect ( " popup_hide " , callable_mp ( this , & Tree : : _text_editor_modal_close ) ) ;
2020-02-21 18:28:45 +01:00
popup_menu - > connect ( " id_pressed " , callable_mp ( this , & Tree : : popup_select ) ) ;
value_editor - > connect ( " value_changed " , callable_mp ( this , & Tree : : value_editor_changed ) ) ;
2014-02-10 02:10:30 +01:00
2018-10-04 19:33:34 +02:00
set_notify_transform ( true ) ;
2014-02-10 02:10:30 +01:00
2017-01-08 23:54:19 +01:00
set_mouse_filter ( MOUSE_FILTER_STOP ) ;
2014-02-10 02:10:30 +01:00
2017-01-09 19:50:08 +01:00
set_clip_contents ( true ) ;
2021-05-16 13:42:28 +02:00
update_cache ( ) ;
2014-02-10 02:10:30 +01:00
}
Tree : : ~ Tree ( ) {
if ( root ) {
2017-03-05 16:44:50 +01:00
memdelete ( root ) ;
2014-02-10 02:10:30 +01:00
}
}