2016-06-18 14:46:12 +02:00
/*************************************************************************/
/* item_list.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
2017-08-27 14:16:55 +02:00
/* https://godotengine.org */
2016-06-18 14:46:12 +02:00
/*************************************************************************/
2021-01-01 20:13:46 +01:00
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
2016-06-18 14:46:12 +02: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
2015-06-06 14:44:38 +02:00
# include "item_list.h"
2020-11-07 23:33:38 +01:00
# include "core/config/project_settings.h"
2018-09-11 18:13:45 +02:00
# include "core/os/os.h"
2020-09-03 13:22:16 +02:00
# include "core/string/translation.h"
void ItemList : : _shape ( int p_idx ) {
Item & item = items . write [ p_idx ] ;
item . text_buf - > clear ( ) ;
if ( item . text_direction = = Control : : TEXT_DIRECTION_INHERITED ) {
item . text_buf - > set_direction ( is_layout_rtl ( ) ? TextServer : : DIRECTION_RTL : TextServer : : DIRECTION_LTR ) ;
} else {
item . text_buf - > set_direction ( ( TextServer : : Direction ) item . text_direction ) ;
}
2021-07-17 23:22:52 +02:00
item . text_buf - > add_string ( item . text , get_theme_font ( SNAME ( " font " ) ) , get_theme_font_size ( SNAME ( " font_size " ) ) , item . opentype_features , ( item . language ! = " " ) ? item . language : TranslationServer : : get_singleton ( ) - > get_tool_locale ( ) ) ;
2020-09-03 13:22:16 +02:00
if ( icon_mode = = ICON_MODE_TOP & & max_text_lines > 0 ) {
item . text_buf - > set_flags ( TextServer : : BREAK_MANDATORY | TextServer : : BREAK_WORD_BOUND | TextServer : : BREAK_GRAPHEME_BOUND ) ;
} else {
item . text_buf - > set_flags ( TextServer : : BREAK_NONE ) ;
}
2021-08-21 00:22:09 +02:00
item . text_buf - > set_text_overrun_behavior ( text_overrun_behavior ) ;
item . text_buf - > set_max_lines_visible ( max_text_lines ) ;
2020-09-03 13:22:16 +02:00
}
2015-06-06 14:44:38 +02:00
2019-11-17 22:45:08 +01:00
int ItemList : : add_item ( const String & p_item , const Ref < Texture2D > & p_texture , bool p_selectable ) {
2015-06-06 14:44:38 +02:00
Item item ;
2017-03-05 16:44:50 +01:00
item . icon = p_texture ;
2018-10-29 17:16:18 +01:00
item . icon_transposed = false ;
2017-03-05 16:44:50 +01:00
item . icon_region = Rect2i ( ) ;
2018-03-11 15:59:50 +01:00
item . icon_modulate = Color ( 1 , 1 , 1 , 1 ) ;
2017-03-05 16:44:50 +01:00
item . text = p_item ;
2021-06-18 00:03:09 +02:00
item . text_buf . instantiate ( ) ;
2017-03-05 16:44:50 +01:00
item . selectable = p_selectable ;
item . selected = false ;
item . disabled = false ;
item . tooltip_enabled = true ;
item . custom_bg = Color ( 0 , 0 , 0 , 0 ) ;
2015-06-06 14:44:38 +02:00
items . push_back ( item ) ;
2019-11-17 22:45:08 +01:00
int item_id = items . size ( ) - 1 ;
2015-06-06 14:44:38 +02:00
2020-09-03 13:22:16 +02:00
_shape ( items . size ( ) - 1 ) ;
2015-06-06 14:44:38 +02:00
update ( ) ;
2017-03-05 16:44:50 +01:00
shape_changed = true ;
2019-11-17 22:45:08 +01:00
return item_id ;
2015-06-06 14:44:38 +02:00
}
2019-11-17 22:45:08 +01:00
int ItemList : : add_icon_item ( const Ref < Texture2D > & p_item , bool p_selectable ) {
2015-06-06 14:44:38 +02:00
Item item ;
2017-03-05 16:44:50 +01:00
item . icon = p_item ;
2018-10-29 17:16:18 +01:00
item . icon_transposed = false ;
2017-03-05 16:44:50 +01:00
item . icon_region = Rect2i ( ) ;
2018-03-11 15:59:50 +01:00
item . icon_modulate = Color ( 1 , 1 , 1 , 1 ) ;
2015-06-06 14:44:38 +02:00
//item.text=p_item;
2021-06-18 00:03:09 +02:00
item . text_buf . instantiate ( ) ;
2017-03-05 16:44:50 +01:00
item . selectable = p_selectable ;
item . selected = false ;
item . disabled = false ;
item . tooltip_enabled = true ;
item . custom_bg = Color ( 0 , 0 , 0 , 0 ) ;
2015-06-06 14:44:38 +02:00
items . push_back ( item ) ;
2019-11-17 22:45:08 +01:00
int item_id = items . size ( ) - 1 ;
2015-06-06 14:44:38 +02:00
update ( ) ;
2017-03-05 16:44:50 +01:00
shape_changed = true ;
2019-11-17 22:45:08 +01:00
return item_id ;
2015-06-06 14:44:38 +02:00
}
2017-03-05 16:44:50 +01:00
void ItemList : : set_item_text ( int p_idx , const String & p_text ) {
ERR_FAIL_INDEX ( p_idx , items . size ( ) ) ;
2015-06-06 14:44:38 +02:00
2018-07-25 03:11:03 +02:00
items . write [ p_idx ] . text = p_text ;
2020-09-03 13:22:16 +02:00
_shape ( p_idx ) ;
2015-06-06 14:44:38 +02:00
update ( ) ;
2017-03-05 16:44:50 +01:00
shape_changed = true ;
2015-06-06 14:44:38 +02:00
}
2017-03-05 16:44:50 +01:00
String ItemList : : get_item_text ( int p_idx ) const {
ERR_FAIL_INDEX_V ( p_idx , items . size ( ) , String ( ) ) ;
2015-06-06 14:44:38 +02:00
return items [ p_idx ] . text ;
}
2020-09-03 13:22:16 +02:00
void ItemList : : set_item_text_direction ( int p_idx , Control : : TextDirection p_text_direction ) {
ERR_FAIL_INDEX ( p_idx , items . size ( ) ) ;
ERR_FAIL_COND ( ( int ) p_text_direction < - 1 | | ( int ) p_text_direction > 3 ) ;
if ( items [ p_idx ] . text_direction ! = p_text_direction ) {
items . write [ p_idx ] . text_direction = p_text_direction ;
_shape ( p_idx ) ;
update ( ) ;
}
}
Control : : TextDirection ItemList : : get_item_text_direction ( int p_idx ) const {
ERR_FAIL_INDEX_V ( p_idx , items . size ( ) , TEXT_DIRECTION_INHERITED ) ;
return items [ p_idx ] . text_direction ;
}
void ItemList : : clear_item_opentype_features ( int p_idx ) {
ERR_FAIL_INDEX ( p_idx , items . size ( ) ) ;
items . write [ p_idx ] . opentype_features . clear ( ) ;
_shape ( p_idx ) ;
update ( ) ;
}
void ItemList : : set_item_opentype_feature ( int p_idx , const String & p_name , int p_value ) {
ERR_FAIL_INDEX ( p_idx , items . size ( ) ) ;
int32_t tag = TS - > name_to_tag ( p_name ) ;
if ( ! items [ p_idx ] . opentype_features . has ( tag ) | | ( int ) items [ p_idx ] . opentype_features [ tag ] ! = p_value ) {
items . write [ p_idx ] . opentype_features [ tag ] = p_value ;
_shape ( p_idx ) ;
update ( ) ;
}
}
int ItemList : : get_item_opentype_feature ( int p_idx , const String & p_name ) const {
ERR_FAIL_INDEX_V ( p_idx , items . size ( ) , - 1 ) ;
int32_t tag = TS - > name_to_tag ( p_name ) ;
if ( ! items [ p_idx ] . opentype_features . has ( tag ) ) {
return - 1 ;
}
return items [ p_idx ] . opentype_features [ tag ] ;
}
void ItemList : : set_item_language ( int p_idx , const String & p_language ) {
ERR_FAIL_INDEX ( p_idx , items . size ( ) ) ;
if ( items [ p_idx ] . language ! = p_language ) {
items . write [ p_idx ] . language = p_language ;
_shape ( p_idx ) ;
update ( ) ;
}
}
String ItemList : : get_item_language ( int p_idx ) const {
ERR_FAIL_INDEX_V ( p_idx , items . size ( ) , " " ) ;
return items [ p_idx ] . language ;
}
2016-09-07 17:21:20 +02:00
void ItemList : : set_item_tooltip_enabled ( int p_idx , const bool p_enabled ) {
2017-03-05 16:44:50 +01:00
ERR_FAIL_INDEX ( p_idx , items . size ( ) ) ;
2018-07-25 03:11:03 +02:00
items . write [ p_idx ] . tooltip_enabled = p_enabled ;
2016-09-07 17:21:20 +02:00
}
bool ItemList : : is_item_tooltip_enabled ( int p_idx ) const {
2017-03-05 16:44:50 +01:00
ERR_FAIL_INDEX_V ( p_idx , items . size ( ) , false ) ;
2016-09-07 17:21:20 +02:00
return items [ p_idx ] . tooltip_enabled ;
}
2017-03-05 16:44:50 +01:00
void ItemList : : set_item_tooltip ( int p_idx , const String & p_tooltip ) {
ERR_FAIL_INDEX ( p_idx , items . size ( ) ) ;
2015-06-06 14:44:38 +02:00
2018-07-25 03:11:03 +02:00
items . write [ p_idx ] . tooltip = p_tooltip ;
2015-06-06 14:44:38 +02:00
update ( ) ;
2017-03-05 16:44:50 +01:00
shape_changed = true ;
2015-06-06 14:44:38 +02:00
}
2017-03-05 16:44:50 +01:00
String ItemList : : get_item_tooltip ( int p_idx ) const {
ERR_FAIL_INDEX_V ( p_idx , items . size ( ) , String ( ) ) ;
2015-06-06 14:44:38 +02:00
return items [ p_idx ] . tooltip ;
}
2019-06-11 20:43:37 +02:00
void ItemList : : set_item_icon ( int p_idx , const Ref < Texture2D > & p_icon ) {
2017-03-05 16:44:50 +01:00
ERR_FAIL_INDEX ( p_idx , items . size ( ) ) ;
2015-06-06 14:44:38 +02:00
2018-07-25 03:11:03 +02:00
items . write [ p_idx ] . icon = p_icon ;
2015-06-06 14:44:38 +02:00
update ( ) ;
2017-03-05 16:44:50 +01:00
shape_changed = true ;
2015-06-06 14:44:38 +02:00
}
2016-03-13 16:23:49 +01:00
2019-06-11 20:43:37 +02:00
Ref < Texture2D > ItemList : : get_item_icon ( int p_idx ) const {
ERR_FAIL_INDEX_V ( p_idx , items . size ( ) , Ref < Texture2D > ( ) ) ;
2015-06-06 14:44:38 +02:00
return items [ p_idx ] . icon ;
}
2018-10-29 17:16:18 +01:00
void ItemList : : set_item_icon_transposed ( int p_idx , const bool p_transposed ) {
ERR_FAIL_INDEX ( p_idx , items . size ( ) ) ;
items . write [ p_idx ] . icon_transposed = p_transposed ;
update ( ) ;
shape_changed = true ;
}
bool ItemList : : is_item_icon_transposed ( int p_idx ) const {
ERR_FAIL_INDEX_V ( p_idx , items . size ( ) , false ) ;
return items [ p_idx ] . icon_transposed ;
}
2017-03-05 16:44:50 +01:00
void ItemList : : set_item_icon_region ( int p_idx , const Rect2 & p_region ) {
ERR_FAIL_INDEX ( p_idx , items . size ( ) ) ;
2016-03-13 16:23:49 +01:00
2018-07-25 03:11:03 +02:00
items . write [ p_idx ] . icon_region = p_region ;
2016-03-13 16:23:49 +01:00
update ( ) ;
2017-03-05 16:44:50 +01:00
shape_changed = true ;
2016-03-13 16:23:49 +01:00
}
Rect2 ItemList : : get_item_icon_region ( int p_idx ) const {
2017-03-05 16:44:50 +01:00
ERR_FAIL_INDEX_V ( p_idx , items . size ( ) , Rect2 ( ) ) ;
2016-03-13 16:23:49 +01:00
return items [ p_idx ] . icon_region ;
}
2018-03-11 15:59:50 +01:00
void ItemList : : set_item_icon_modulate ( int p_idx , const Color & p_modulate ) {
ERR_FAIL_INDEX ( p_idx , items . size ( ) ) ;
2018-07-25 03:11:03 +02:00
items . write [ p_idx ] . icon_modulate = p_modulate ;
2018-03-11 15:59:50 +01:00
update ( ) ;
}
Color ItemList : : get_item_icon_modulate ( int p_idx ) const {
ERR_FAIL_INDEX_V ( p_idx , items . size ( ) , Color ( ) ) ;
return items [ p_idx ] . icon_modulate ;
}
2017-03-05 16:44:50 +01:00
void ItemList : : set_item_custom_bg_color ( int p_idx , const Color & p_custom_bg_color ) {
ERR_FAIL_INDEX ( p_idx , items . size ( ) ) ;
2015-06-22 05:03:19 +02:00
2018-07-25 03:11:03 +02:00
items . write [ p_idx ] . custom_bg = p_custom_bg_color ;
2021-08-07 13:06:50 +02:00
update ( ) ;
2015-06-22 05:03:19 +02:00
}
Color ItemList : : get_item_custom_bg_color ( int p_idx ) const {
2017-03-05 16:44:50 +01:00
ERR_FAIL_INDEX_V ( p_idx , items . size ( ) , Color ( ) ) ;
2015-06-22 05:03:19 +02:00
return items [ p_idx ] . custom_bg ;
}
2017-09-03 09:44:59 +02:00
void ItemList : : set_item_custom_fg_color ( int p_idx , const Color & p_custom_fg_color ) {
ERR_FAIL_INDEX ( p_idx , items . size ( ) ) ;
2018-07-25 03:11:03 +02:00
items . write [ p_idx ] . custom_fg = p_custom_fg_color ;
2021-08-07 13:06:50 +02:00
update ( ) ;
2017-09-03 09:44:59 +02:00
}
Color ItemList : : get_item_custom_fg_color ( int p_idx ) const {
ERR_FAIL_INDEX_V ( p_idx , items . size ( ) , Color ( ) ) ;
return items [ p_idx ] . custom_fg ;
}
2019-06-11 20:43:37 +02:00
void ItemList : : set_item_tag_icon ( int p_idx , const Ref < Texture2D > & p_tag_icon ) {
2017-03-05 16:44:50 +01:00
ERR_FAIL_INDEX ( p_idx , items . size ( ) ) ;
2015-06-06 14:44:38 +02:00
2018-07-25 03:11:03 +02:00
items . write [ p_idx ] . tag_icon = p_tag_icon ;
2015-06-06 14:44:38 +02:00
update ( ) ;
2017-03-05 16:44:50 +01:00
shape_changed = true ;
2015-06-06 14:44:38 +02:00
}
2020-05-14 14:29:06 +02:00
2019-06-11 20:43:37 +02:00
Ref < Texture2D > ItemList : : get_item_tag_icon ( int p_idx ) const {
ERR_FAIL_INDEX_V ( p_idx , items . size ( ) , Ref < Texture2D > ( ) ) ;
2015-06-06 14:44:38 +02:00
return items [ p_idx ] . tag_icon ;
}
2017-03-05 16:44:50 +01:00
void ItemList : : set_item_selectable ( int p_idx , bool p_selectable ) {
ERR_FAIL_INDEX ( p_idx , items . size ( ) ) ;
2015-06-06 14:44:38 +02:00
2018-07-25 03:11:03 +02:00
items . write [ p_idx ] . selectable = p_selectable ;
2015-06-06 14:44:38 +02:00
}
2017-03-05 16:44:50 +01:00
bool ItemList : : is_item_selectable ( int p_idx ) const {
ERR_FAIL_INDEX_V ( p_idx , items . size ( ) , false ) ;
2015-06-06 14:44:38 +02:00
return items [ p_idx ] . selectable ;
}
2017-03-05 16:44:50 +01:00
void ItemList : : set_item_disabled ( int p_idx , bool p_disabled ) {
ERR_FAIL_INDEX ( p_idx , items . size ( ) ) ;
2015-06-06 14:44:38 +02:00
2018-07-25 03:11:03 +02:00
items . write [ p_idx ] . disabled = p_disabled ;
2016-07-21 23:24:56 +02:00
update ( ) ;
2015-06-06 14:44:38 +02:00
}
2017-03-05 16:44:50 +01:00
bool ItemList : : is_item_disabled ( int p_idx ) const {
ERR_FAIL_INDEX_V ( p_idx , items . size ( ) , false ) ;
2015-06-06 14:44:38 +02:00
return items [ p_idx ] . disabled ;
}
2017-03-05 16:44:50 +01:00
void ItemList : : set_item_metadata ( int p_idx , const Variant & p_metadata ) {
ERR_FAIL_INDEX ( p_idx , items . size ( ) ) ;
2015-06-06 14:44:38 +02:00
2018-07-25 03:11:03 +02:00
items . write [ p_idx ] . metadata = p_metadata ;
2015-06-06 14:44:38 +02:00
update ( ) ;
2017-03-05 16:44:50 +01:00
shape_changed = true ;
2015-06-06 14:44:38 +02:00
}
2017-03-05 16:44:50 +01:00
Variant ItemList : : get_item_metadata ( int p_idx ) const {
ERR_FAIL_INDEX_V ( p_idx , items . size ( ) , Variant ( ) ) ;
2015-06-06 14:44:38 +02:00
return items [ p_idx ] . metadata ;
}
2020-05-14 14:29:06 +02:00
2017-03-05 16:44:50 +01:00
void ItemList : : select ( int p_idx , bool p_single ) {
ERR_FAIL_INDEX ( p_idx , items . size ( ) ) ;
2015-06-06 14:44:38 +02:00
2017-03-05 16:44:50 +01:00
if ( p_single | | select_mode = = SELECT_SINGLE ) {
2016-07-21 23:24:56 +02:00
if ( ! items [ p_idx ] . selectable | | items [ p_idx ] . disabled ) {
2015-06-06 14:44:38 +02:00
return ;
}
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < items . size ( ) ; i + + ) {
2018-07-25 03:11:03 +02:00
items . write [ i ] . selected = p_idx = = i ;
2015-06-06 14:44:38 +02:00
}
2017-03-05 16:44:50 +01:00
current = p_idx ;
ensure_selected_visible = false ;
2015-06-06 14:44:38 +02:00
} else {
2016-07-21 23:24:56 +02:00
if ( items [ p_idx ] . selectable & & ! items [ p_idx ] . disabled ) {
2018-07-25 03:11:03 +02:00
items . write [ p_idx ] . selected = true ;
2015-06-06 14:44:38 +02:00
}
}
update ( ) ;
}
2020-05-14 14:29:06 +02:00
2020-12-21 11:26:41 +01:00
void ItemList : : deselect ( int p_idx ) {
2017-03-05 16:44:50 +01:00
ERR_FAIL_INDEX ( p_idx , items . size ( ) ) ;
2015-06-06 14:44:38 +02:00
2017-03-05 16:44:50 +01:00
if ( select_mode ! = SELECT_MULTI ) {
2018-07-25 03:11:03 +02:00
items . write [ p_idx ] . selected = false ;
2017-03-05 16:44:50 +01:00
current = - 1 ;
2015-06-06 14:44:38 +02:00
} else {
2018-07-25 03:11:03 +02:00
items . write [ p_idx ] . selected = false ;
2015-06-06 14:44:38 +02:00
}
update ( ) ;
}
2017-11-24 14:39:02 +01:00
2020-12-21 11:26:41 +01:00
void ItemList : : deselect_all ( ) {
2020-05-14 16:41:43 +02:00
if ( items . size ( ) < 1 ) {
2017-11-24 14:39:02 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2017-11-24 14:39:02 +01:00
for ( int i = 0 ; i < items . size ( ) ; i + + ) {
2018-07-25 03:11:03 +02:00
items . write [ i ] . selected = false ;
2017-11-24 14:39:02 +01:00
}
2018-07-18 13:46:02 +02:00
current = - 1 ;
2017-11-24 14:39:02 +01:00
update ( ) ;
}
2017-03-05 16:44:50 +01:00
bool ItemList : : is_selected ( int p_idx ) const {
ERR_FAIL_INDEX_V ( p_idx , items . size ( ) , false ) ;
2015-06-06 14:44:38 +02:00
return items [ p_idx ] . selected ;
}
void ItemList : : set_current ( int p_current ) {
2017-03-05 16:44:50 +01:00
ERR_FAIL_INDEX ( p_current , items . size ( ) ) ;
2015-06-06 14:44:38 +02:00
2020-05-14 16:41:43 +02:00
if ( select_mode = = SELECT_SINGLE ) {
2017-03-05 16:44:50 +01:00
select ( p_current , true ) ;
2020-05-14 16:41:43 +02:00
} else {
2017-03-05 16:44:50 +01:00
current = p_current ;
2015-06-06 14:44:38 +02:00
update ( ) ;
}
}
int ItemList : : get_current ( ) const {
return current ;
}
2018-03-13 15:19:04 +01:00
void ItemList : : move_item ( int p_from_idx , int p_to_idx ) {
ERR_FAIL_INDEX ( p_from_idx , items . size ( ) ) ;
ERR_FAIL_INDEX ( p_to_idx , items . size ( ) ) ;
2015-11-17 13:46:08 +01:00
2018-03-13 15:19:04 +01:00
if ( is_anything_selected ( ) & & get_selected_items ( ) [ 0 ] = = p_from_idx ) {
current = p_to_idx ;
2015-11-17 13:46:08 +01:00
}
2018-03-13 15:19:04 +01:00
Item item = items [ p_from_idx ] ;
items . remove ( p_from_idx ) ;
items . insert ( p_to_idx , item ) ;
2015-11-17 13:46:08 +01:00
update ( ) ;
2018-03-13 15:19:04 +01:00
shape_changed = true ;
2015-11-17 13:46:08 +01:00
}
2015-06-06 14:44:38 +02:00
2017-03-05 16:44:50 +01:00
int ItemList : : get_item_count ( ) const {
2015-06-06 14:44:38 +02:00
return items . size ( ) ;
}
2020-05-14 14:29:06 +02:00
2017-03-05 16:44:50 +01:00
void ItemList : : remove_item ( int p_idx ) {
ERR_FAIL_INDEX ( p_idx , items . size ( ) ) ;
2015-06-06 14:44:38 +02:00
items . remove ( p_idx ) ;
2021-05-07 15:41:39 +02:00
if ( current = = p_idx ) {
current = - 1 ;
}
2015-06-06 14:44:38 +02:00
update ( ) ;
2017-03-05 16:44:50 +01:00
shape_changed = true ;
defer_select_single = - 1 ;
2015-06-06 14:44:38 +02:00
}
2017-03-05 16:44:50 +01:00
void ItemList : : clear ( ) {
2015-06-06 14:44:38 +02:00
items . clear ( ) ;
2017-03-05 16:44:50 +01:00
current = - 1 ;
ensure_selected_visible = false ;
2015-06-06 14:44:38 +02:00
update ( ) ;
2017-03-05 16:44:50 +01:00
shape_changed = true ;
defer_select_single = - 1 ;
2015-06-06 14:44:38 +02:00
}
2017-03-05 16:44:50 +01:00
void ItemList : : set_fixed_column_width ( int p_size ) {
ERR_FAIL_COND ( p_size < 0 ) ;
fixed_column_width = p_size ;
2015-06-06 14:44:38 +02:00
update ( ) ;
2017-03-05 16:44:50 +01:00
shape_changed = true ;
2015-06-06 14:44:38 +02:00
}
2020-05-14 14:29:06 +02:00
2017-03-05 16:44:50 +01:00
int ItemList : : get_fixed_column_width ( ) const {
2015-06-06 14:44:38 +02:00
return fixed_column_width ;
}
2017-03-05 16:44:50 +01:00
void ItemList : : set_same_column_width ( bool p_enable ) {
same_column_width = p_enable ;
2016-05-27 21:42:51 +02:00
update ( ) ;
2017-03-05 16:44:50 +01:00
shape_changed = true ;
2016-05-27 21:42:51 +02:00
}
2020-05-14 14:29:06 +02:00
2017-08-11 13:34:06 +02:00
bool ItemList : : is_same_column_width ( ) const {
2016-05-27 21:42:51 +02:00
return same_column_width ;
}
2017-03-05 16:44:50 +01:00
void ItemList : : set_max_text_lines ( int p_lines ) {
ERR_FAIL_COND ( p_lines < 1 ) ;
2020-09-03 13:22:16 +02:00
if ( max_text_lines ! = p_lines ) {
max_text_lines = p_lines ;
for ( int i = 0 ; i < items . size ( ) ; i + + ) {
if ( icon_mode = = ICON_MODE_TOP & & max_text_lines > 0 ) {
items . write [ i ] . text_buf - > set_flags ( TextServer : : BREAK_MANDATORY | TextServer : : BREAK_WORD_BOUND | TextServer : : BREAK_GRAPHEME_BOUND ) ;
2021-08-21 00:22:09 +02:00
items . write [ i ] . text_buf - > set_max_lines_visible ( p_lines ) ;
2020-09-03 13:22:16 +02:00
} else {
items . write [ i ] . text_buf - > set_flags ( TextServer : : BREAK_NONE ) ;
}
}
shape_changed = true ;
update ( ) ;
}
2015-06-06 14:44:38 +02:00
}
2020-05-14 14:29:06 +02:00
2017-03-05 16:44:50 +01:00
int ItemList : : get_max_text_lines ( ) const {
2015-06-06 14:44:38 +02:00
return max_text_lines ;
}
2017-03-05 16:44:50 +01:00
void ItemList : : set_max_columns ( int p_amount ) {
ERR_FAIL_COND ( p_amount < 0 ) ;
max_columns = p_amount ;
2015-06-06 14:44:38 +02:00
update ( ) ;
2019-11-06 21:26:51 +01:00
shape_changed = true ;
2015-06-06 14:44:38 +02:00
}
2020-05-14 14:29:06 +02:00
2017-03-05 16:44:50 +01:00
int ItemList : : get_max_columns ( ) const {
2015-06-06 14:44:38 +02:00
return max_columns ;
}
void ItemList : : set_select_mode ( SelectMode p_mode ) {
2017-03-05 16:44:50 +01:00
select_mode = p_mode ;
2015-06-06 14:44:38 +02:00
update ( ) ;
}
ItemList : : SelectMode ItemList : : get_select_mode ( ) const {
return select_mode ;
}
2017-03-05 16:44:50 +01:00
void ItemList : : set_icon_mode ( IconMode p_mode ) {
2019-10-05 19:17:07 +02:00
ERR_FAIL_INDEX ( ( int ) p_mode , 2 ) ;
2020-09-03 13:22:16 +02:00
if ( icon_mode ! = p_mode ) {
icon_mode = p_mode ;
for ( int i = 0 ; i < items . size ( ) ; i + + ) {
if ( icon_mode = = ICON_MODE_TOP & & max_text_lines > 0 ) {
items . write [ i ] . text_buf - > set_flags ( TextServer : : BREAK_MANDATORY | TextServer : : BREAK_WORD_BOUND | TextServer : : BREAK_GRAPHEME_BOUND ) ;
} else {
items . write [ i ] . text_buf - > set_flags ( TextServer : : BREAK_NONE ) ;
}
}
shape_changed = true ;
update ( ) ;
}
2015-06-06 14:44:38 +02:00
}
2018-10-29 17:16:18 +01:00
2017-03-05 16:44:50 +01:00
ItemList : : IconMode ItemList : : get_icon_mode ( ) const {
2015-06-06 14:44:38 +02:00
return icon_mode ;
}
2017-03-05 16:44:50 +01:00
void ItemList : : set_fixed_icon_size ( const Size2 & p_size ) {
fixed_icon_size = p_size ;
2016-05-15 04:48:23 +02:00
update ( ) ;
}
2016-06-12 21:51:27 +02:00
Size2 ItemList : : get_fixed_icon_size ( ) const {
return fixed_icon_size ;
2016-05-15 04:48:23 +02:00
}
2020-05-14 14:29:06 +02:00
2016-03-13 16:23:49 +01:00
Size2 ItemList : : Item : : get_icon_size ( ) const {
2020-05-14 16:41:43 +02:00
if ( icon . is_null ( ) ) {
2016-03-13 16:23:49 +01:00
return Size2 ( ) ;
2020-05-14 16:41:43 +02:00
}
2016-03-13 16:23:49 +01:00
2018-10-29 17:16:18 +01:00
Size2 size_result = Size2 ( icon_region . size ) . abs ( ) ;
2020-05-14 16:41:43 +02:00
if ( icon_region . size . x = = 0 | | icon_region . size . y = = 0 ) {
2018-11-07 18:29:24 +01:00
size_result = icon - > get_size ( ) ;
2020-05-14 16:41:43 +02:00
}
2018-11-07 18:29:24 +01:00
2018-10-29 17:16:18 +01:00
if ( icon_transposed ) {
Size2 size_tmp = size_result ;
size_result . x = size_tmp . y ;
size_result . y = size_tmp . x ;
}
return size_result ;
2016-03-13 16:23:49 +01:00
}
2015-06-06 14:44:38 +02:00
2017-05-20 17:38:03 +02:00
void ItemList : : _gui_input ( const Ref < InputEvent > & p_event ) {
2021-04-05 08:52:21 +02:00
ERR_FAIL_COND ( p_event . is_null ( ) ) ;
2019-05-21 18:53:29 +02:00
double prev_scroll = scroll_bar - > get_value ( ) ;
2017-05-20 17:38:03 +02:00
Ref < InputEventMouseMotion > mm = p_event ;
if ( defer_select_single > = 0 & & mm . is_valid ( ) ) {
2017-03-05 16:44:50 +01:00
defer_select_single = - 1 ;
2016-05-04 22:41:58 +02:00
return ;
}
2016-05-16 01:25:51 +02:00
2017-05-20 17:38:03 +02:00
Ref < InputEventMouseButton > mb = p_event ;
2021-01-08 04:37:37 +01:00
if ( defer_select_single > = 0 & & mb . is_valid ( ) & & mb - > get_button_index ( ) = = MOUSE_BUTTON_LEFT & & ! mb - > is_pressed ( ) ) {
2017-03-05 16:44:50 +01:00
select ( defer_select_single , true ) ;
2016-05-16 01:25:51 +02:00
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " multi_selected " ) , defer_select_single , true ) ;
2017-03-05 16:44:50 +01:00
defer_select_single = - 1 ;
2016-05-04 22:41:58 +02:00
return ;
}
2021-01-08 04:37:37 +01:00
if ( mb . is_valid ( ) & & ( mb - > get_button_index ( ) = = MOUSE_BUTTON_LEFT | | ( allow_rmb_select & & mb - > get_button_index ( ) = = MOUSE_BUTTON_RIGHT ) ) & & mb - > is_pressed ( ) ) {
2017-03-05 16:44:50 +01:00
search_string = " " ; //any mousepress cancels
2017-08-02 21:48:50 +02:00
Vector2 pos = mb - > get_position ( ) ;
2021-07-17 23:22:52 +02:00
Ref < StyleBox > bg = get_theme_stylebox ( SNAME ( " bg " ) ) ;
2017-03-05 16:44:50 +01:00
pos - = bg - > get_offset ( ) ;
pos . y + = scroll_bar - > get_value ( ) ;
2015-06-06 14:44:38 +02:00
2020-09-03 13:22:16 +02:00
if ( is_layout_rtl ( ) ) {
pos . x = get_size ( ) . width - pos . x ;
}
2015-06-06 14:44:38 +02:00
int closest = - 1 ;
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < items . size ( ) ; i + + ) {
2015-06-06 14:44:38 +02:00
Rect2 rc = items [ i ] . rect_cache ;
2017-03-05 16:44:50 +01:00
if ( i % current_columns = = current_columns - 1 ) {
rc . size . width = get_size ( ) . width ; //not right but works
2015-06-06 14:44:38 +02:00
}
if ( rc . has_point ( pos ) ) {
2017-03-05 16:44:50 +01:00
closest = i ;
2015-06-06 14:44:38 +02:00
break ;
}
}
2017-03-05 16:44:50 +01:00
if ( closest ! = - 1 ) {
2015-06-06 14:44:38 +02:00
int i = closest ;
2021-04-24 22:33:50 +02:00
if ( select_mode = = SELECT_MULTI & & items [ i ] . selected & & mb - > is_command_pressed ( ) ) {
2020-12-21 11:26:41 +01:00
deselect ( i ) ;
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " multi_selected " ) , i , false ) ;
2016-05-16 01:25:51 +02:00
2021-04-24 22:33:50 +02:00
} else if ( select_mode = = SELECT_MULTI & & mb - > is_shift_pressed ( ) & & current > = 0 & & current < items . size ( ) & & current ! = i ) {
2015-06-06 14:44:38 +02:00
int from = current ;
int to = i ;
2017-03-05 16:44:50 +01:00
if ( i < current ) {
SWAP ( from , to ) ;
2015-06-06 14:44:38 +02:00
}
2017-03-05 16:44:50 +01:00
for ( int j = from ; j < = to ; j + + ) {
2015-06-06 14:44:38 +02:00
bool selected = ! items [ j ] . selected ;
2017-03-05 16:44:50 +01:00
select ( j , false ) ;
2020-05-14 16:41:43 +02:00
if ( selected ) {
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " multi_selected " ) , j , true ) ;
2020-05-14 16:41:43 +02:00
}
2015-06-06 14:44:38 +02:00
}
2016-05-16 01:25:51 +02:00
2021-01-08 04:37:37 +01:00
if ( mb - > get_button_index ( ) = = MOUSE_BUTTON_RIGHT ) {
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " item_rmb_selected " ) , i , get_local_mouse_position ( ) ) ;
2016-05-16 01:25:51 +02:00
}
2015-06-06 14:44:38 +02:00
} else {
2021-04-24 22:33:50 +02:00
if ( ! mb - > is_double_click ( ) & & ! mb - > is_command_pressed ( ) & & select_mode = = SELECT_MULTI & & items [ i ] . selectable & & ! items [ i ] . disabled & & items [ i ] . selected & & mb - > get_button_index ( ) = = MOUSE_BUTTON_LEFT ) {
2017-03-05 16:44:50 +01:00
defer_select_single = i ;
2016-05-04 22:41:58 +02:00
return ;
}
2021-01-08 04:37:37 +01:00
if ( items [ i ] . selected & & mb - > get_button_index ( ) = = MOUSE_BUTTON_RIGHT ) {
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " item_rmb_selected " ) , i , get_local_mouse_position ( ) ) ;
2016-05-16 01:25:51 +02:00
} else {
2018-02-14 04:24:57 +01:00
bool selected = items [ i ] . selected ;
2015-06-06 14:44:38 +02:00
2021-04-24 22:33:50 +02:00
select ( i , select_mode = = SELECT_SINGLE | | ! mb - > is_command_pressed ( ) ) ;
2016-05-16 01:25:51 +02:00
2018-02-14 04:24:57 +01:00
if ( ! selected | | allow_reselect ) {
2017-03-05 16:44:50 +01:00
if ( select_mode = = SELECT_SINGLE ) {
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " item_selected " ) , i ) ;
2020-05-14 16:41:43 +02:00
} else {
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " multi_selected " ) , i , true ) ;
2020-05-14 16:41:43 +02:00
}
2016-05-16 01:25:51 +02:00
}
2021-01-08 04:37:37 +01:00
if ( mb - > get_button_index ( ) = = MOUSE_BUTTON_RIGHT ) {
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " item_rmb_selected " ) , i , get_local_mouse_position ( ) ) ;
2021-04-13 10:25:44 +02:00
} else if ( /*select_mode==SELECT_SINGLE &&*/ mb - > is_double_click ( ) ) {
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " item_activated " ) , i ) ;
2016-05-16 01:25:51 +02:00
}
}
2015-06-06 14:44:38 +02:00
}
2017-11-20 19:25:13 +01:00
return ;
}
2021-01-08 04:37:37 +01:00
if ( mb - > get_button_index ( ) = = MOUSE_BUTTON_RIGHT ) {
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " rmb_clicked " ) , mb - > get_position ( ) ) ;
2017-11-20 19:25:13 +01:00
2015-06-06 14:44:38 +02:00
return ;
}
2017-11-24 14:39:02 +01:00
// Since closest is null, more likely we clicked on empty space, so send signal to interested controls. Allows, for example, implement items deselecting.
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " nothing_selected " ) ) ;
2015-06-06 14:44:38 +02:00
}
2021-01-08 04:37:37 +01:00
if ( mb . is_valid ( ) & & mb - > get_button_index ( ) = = MOUSE_BUTTON_WHEEL_UP & & mb - > is_pressed ( ) ) {
2017-05-20 17:38:03 +02:00
scroll_bar - > set_value ( scroll_bar - > get_value ( ) - scroll_bar - > get_page ( ) * mb - > get_factor ( ) / 8 ) ;
2015-06-06 14:44:38 +02:00
}
2021-01-08 04:37:37 +01:00
if ( mb . is_valid ( ) & & mb - > get_button_index ( ) = = MOUSE_BUTTON_WHEEL_DOWN & & mb - > is_pressed ( ) ) {
2017-05-20 17:38:03 +02:00
scroll_bar - > set_value ( scroll_bar - > get_value ( ) + scroll_bar - > get_page ( ) * mb - > get_factor ( ) / 8 ) ;
2015-06-06 14:44:38 +02:00
}
2017-05-20 17:38:03 +02:00
if ( p_event - > is_pressed ( ) & & items . size ( ) > 0 ) {
if ( p_event - > is_action ( " ui_up " ) ) {
2017-03-05 16:44:50 +01:00
if ( search_string ! = " " ) {
2015-06-06 14:44:38 +02:00
uint64_t now = OS : : get_singleton ( ) - > get_ticks_msec ( ) ;
2017-03-05 16:44:50 +01:00
uint64_t diff = now - search_time_msec ;
2015-06-06 14:44:38 +02:00
2017-08-31 23:30:35 +02:00
if ( diff < uint64_t ( ProjectSettings : : get_singleton ( ) - > get ( " gui/timers/incremental_search_max_interval_msec " ) ) * 2 ) {
2017-03-05 16:44:50 +01:00
for ( int i = current - 1 ; i > = 0 ; i - - ) {
2015-06-06 14:44:38 +02:00
if ( items [ i ] . text . begins_with ( search_string ) ) {
set_current ( i ) ;
ensure_current_is_visible ( ) ;
2017-03-05 16:44:50 +01:00
if ( select_mode = = SELECT_SINGLE ) {
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " item_selected " ) , current ) ;
2015-06-06 14:44:38 +02:00
}
break ;
}
}
accept_event ( ) ;
return ;
}
}
2017-03-05 16:44:50 +01:00
if ( current > = current_columns ) {
set_current ( current - current_columns ) ;
2015-06-06 14:44:38 +02:00
ensure_current_is_visible ( ) ;
2017-03-05 16:44:50 +01:00
if ( select_mode = = SELECT_SINGLE ) {
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " item_selected " ) , current ) ;
2015-06-06 14:44:38 +02:00
}
accept_event ( ) ;
}
2017-05-20 17:38:03 +02:00
} else if ( p_event - > is_action ( " ui_down " ) ) {
2017-03-05 16:44:50 +01:00
if ( search_string ! = " " ) {
2015-06-06 14:44:38 +02:00
uint64_t now = OS : : get_singleton ( ) - > get_ticks_msec ( ) ;
2017-03-05 16:44:50 +01:00
uint64_t diff = now - search_time_msec ;
2015-06-06 14:44:38 +02:00
2017-08-31 23:30:35 +02:00
if ( diff < uint64_t ( ProjectSettings : : get_singleton ( ) - > get ( " gui/timers/incremental_search_max_interval_msec " ) ) * 2 ) {
2017-03-05 16:44:50 +01:00
for ( int i = current + 1 ; i < items . size ( ) ; i + + ) {
2015-06-06 14:44:38 +02:00
if ( items [ i ] . text . begins_with ( search_string ) ) {
set_current ( i ) ;
ensure_current_is_visible ( ) ;
2017-03-05 16:44:50 +01:00
if ( select_mode = = SELECT_SINGLE ) {
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " item_selected " ) , current ) ;
2015-06-06 14:44:38 +02:00
}
break ;
}
}
accept_event ( ) ;
return ;
}
}
2017-03-05 16:44:50 +01:00
if ( current < items . size ( ) - current_columns ) {
set_current ( current + current_columns ) ;
2015-06-06 14:44:38 +02:00
ensure_current_is_visible ( ) ;
2017-03-05 16:44:50 +01:00
if ( select_mode = = SELECT_SINGLE ) {
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " item_selected " ) , current ) ;
2015-06-06 14:44:38 +02:00
}
accept_event ( ) ;
}
2017-05-20 17:38:03 +02:00
} else if ( p_event - > is_action ( " ui_page_up " ) ) {
2017-03-05 16:44:50 +01:00
search_string = " " ; //any mousepress cancels
2015-06-06 14:44:38 +02:00
2017-03-05 16:44:50 +01:00
for ( int i = 4 ; i > 0 ; i - - ) {
if ( current - current_columns * i > = 0 ) {
set_current ( current - current_columns * i ) ;
2015-06-06 14:44:38 +02:00
ensure_current_is_visible ( ) ;
2017-03-05 16:44:50 +01:00
if ( select_mode = = SELECT_SINGLE ) {
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " item_selected " ) , current ) ;
2015-06-06 14:44:38 +02:00
}
accept_event ( ) ;
break ;
}
}
2017-05-20 17:38:03 +02:00
} else if ( p_event - > is_action ( " ui_page_down " ) ) {
2017-03-05 16:44:50 +01:00
search_string = " " ; //any mousepress cancels
2015-06-06 14:44:38 +02:00
2017-03-05 16:44:50 +01:00
for ( int i = 4 ; i > 0 ; i - - ) {
if ( current + current_columns * i < items . size ( ) ) {
set_current ( current + current_columns * i ) ;
2015-06-06 14:44:38 +02:00
ensure_current_is_visible ( ) ;
2017-03-05 16:44:50 +01:00
if ( select_mode = = SELECT_SINGLE ) {
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " item_selected " ) , current ) ;
2015-06-06 14:44:38 +02:00
}
accept_event ( ) ;
break ;
}
}
2017-05-20 17:38:03 +02:00
} else if ( p_event - > is_action ( " ui_left " ) ) {
2017-03-05 16:44:50 +01:00
search_string = " " ; //any mousepress cancels
2015-06-06 14:44:38 +02:00
2017-03-05 16:44:50 +01:00
if ( current % current_columns ! = 0 ) {
set_current ( current - 1 ) ;
2015-06-06 14:44:38 +02:00
ensure_current_is_visible ( ) ;
2017-03-05 16:44:50 +01:00
if ( select_mode = = SELECT_SINGLE ) {
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " item_selected " ) , current ) ;
2015-06-06 14:44:38 +02:00
}
accept_event ( ) ;
}
2017-05-20 17:38:03 +02:00
} else if ( p_event - > is_action ( " ui_right " ) ) {
2017-03-05 16:44:50 +01:00
search_string = " " ; //any mousepress cancels
2015-06-06 14:44:38 +02:00
2018-04-14 14:36:53 +02:00
if ( current % current_columns ! = ( current_columns - 1 ) & & current + 1 < items . size ( ) ) {
2017-03-05 16:44:50 +01:00
set_current ( current + 1 ) ;
2015-06-06 14:44:38 +02:00
ensure_current_is_visible ( ) ;
2017-03-05 16:44:50 +01:00
if ( select_mode = = SELECT_SINGLE ) {
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " item_selected " ) , current ) ;
2015-06-06 14:44:38 +02:00
}
accept_event ( ) ;
}
2017-05-20 17:38:03 +02:00
} else if ( p_event - > is_action ( " ui_cancel " ) ) {
2017-03-05 16:44:50 +01:00
search_string = " " ;
2019-01-17 15:54:24 +01:00
} else if ( p_event - > is_action ( " ui_select " ) & & select_mode = = SELECT_MULTI ) {
if ( current > = 0 & & current < items . size ( ) ) {
2016-07-21 23:24:56 +02:00
if ( items [ current ] . selectable & & ! items [ current ] . disabled & & ! items [ current ] . selected ) {
2017-03-05 16:44:50 +01:00
select ( current , false ) ;
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " multi_selected " ) , current , true ) ;
2015-06-06 14:44:38 +02:00
} else if ( items [ current ] . selected ) {
2020-12-21 11:26:41 +01:00
deselect ( current ) ;
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " multi_selected " ) , current , false ) ;
2015-06-06 14:44:38 +02:00
}
}
2017-05-20 17:38:03 +02:00
} else if ( p_event - > is_action ( " ui_accept " ) ) {
2021-03-12 14:35:16 +01:00
search_string = " " ; //any mousepress cancels
2015-06-06 14:44:38 +02:00
2017-03-05 16:44:50 +01:00
if ( current > = 0 & & current < items . size ( ) ) {
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " item_activated " ) , current ) ;
2015-06-06 14:44:38 +02:00
}
2017-05-20 17:38:03 +02:00
} else {
Ref < InputEventKey > k = p_event ;
2015-06-06 14:44:38 +02:00
2017-05-20 17:38:03 +02:00
if ( k . is_valid ( ) & & k - > get_unicode ( ) ) {
2015-06-06 14:44:38 +02:00
uint64_t now = OS : : get_singleton ( ) - > get_ticks_msec ( ) ;
2017-03-05 16:44:50 +01:00
uint64_t diff = now - search_time_msec ;
uint64_t max_interval = uint64_t ( GLOBAL_DEF ( " gui/timers/incremental_search_max_interval_msec " , 2000 ) ) ;
2015-06-06 14:44:38 +02:00
search_time_msec = now ;
2017-03-05 16:44:50 +01:00
if ( diff > max_interval ) {
search_string = " " ;
2015-06-06 14:44:38 +02:00
}
2020-05-14 16:41:43 +02:00
if ( String : : chr ( k - > get_unicode ( ) ) ! = search_string ) {
2019-05-11 18:32:53 +02:00
search_string + = String : : chr ( k - > get_unicode ( ) ) ;
2020-05-14 16:41:43 +02:00
}
2019-05-11 18:32:53 +02:00
for ( int i = current + 1 ; i < = items . size ( ) ; i + + ) {
if ( i = = items . size ( ) ) {
2020-05-14 16:41:43 +02:00
if ( current = = 0 | | current = = - 1 ) {
2019-05-11 18:32:53 +02:00
break ;
2020-05-14 16:41:43 +02:00
} else {
2019-05-11 18:32:53 +02:00
i = 0 ;
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 ( i = = current ) {
2019-05-11 18:32:53 +02:00
break ;
2020-05-14 16:41:43 +02:00
}
2019-05-11 18:32:53 +02:00
if ( items [ i ] . text . findn ( search_string ) = = 0 ) {
2015-06-06 14:44:38 +02:00
set_current ( i ) ;
ensure_current_is_visible ( ) ;
2017-03-05 16:44:50 +01:00
if ( select_mode = = SELECT_SINGLE ) {
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " item_selected " ) , current ) ;
2015-06-06 14:44:38 +02:00
}
break ;
}
}
}
}
}
2017-11-01 21:49:39 +01:00
Ref < InputEventPanGesture > pan_gesture = p_event ;
if ( pan_gesture . is_valid ( ) ) {
scroll_bar - > set_value ( scroll_bar - > get_value ( ) + scroll_bar - > get_page ( ) * pan_gesture - > get_delta ( ) . y / 8 ) ;
}
2019-05-21 18:53:29 +02:00
2020-05-14 16:41:43 +02:00
if ( scroll_bar - > get_value ( ) ! = prev_scroll ) {
2019-05-21 18:53:29 +02:00
accept_event ( ) ; //accept event if scroll changed
2020-05-14 16:41:43 +02:00
}
2015-06-06 14:44:38 +02:00
}
void ItemList : : ensure_current_is_visible ( ) {
2017-03-05 16:44:50 +01:00
ensure_selected_visible = true ;
2015-08-24 01:15:56 +02:00
update ( ) ;
2015-06-06 14:44:38 +02:00
}
2016-06-12 21:51:27 +02:00
static Rect2 _adjust_to_max_size ( Size2 p_size , Size2 p_max_size ) {
2017-03-05 16:44:50 +01:00
Size2 size = p_max_size ;
2016-06-12 21:51:27 +02:00
int tex_width = p_size . width * size . height / p_size . height ;
int tex_height = size . height ;
2016-05-15 04:48:23 +02:00
2017-03-05 16:44:50 +01:00
if ( tex_width > size . width ) {
tex_width = size . width ;
tex_height = p_size . height * tex_width / p_size . width ;
2016-05-15 04:48:23 +02:00
}
2017-03-05 16:44:50 +01:00
int ofs_x = ( size . width - tex_width ) / 2 ;
int ofs_y = ( size . height - tex_height ) / 2 ;
2016-05-15 04:48:23 +02:00
2017-03-05 16:44:50 +01:00
return Rect2 ( ofs_x , ofs_y , tex_width , tex_height ) ;
2016-05-15 04:48:23 +02:00
}
2015-06-06 14:44:38 +02:00
void ItemList : : _notification ( int p_what ) {
2017-03-05 16:44:50 +01:00
if ( p_what = = NOTIFICATION_RESIZED ) {
shape_changed = true ;
2015-06-06 14:44:38 +02:00
update ( ) ;
}
2020-09-03 13:22:16 +02:00
if ( ( p_what = = NOTIFICATION_LAYOUT_DIRECTION_CHANGED ) | | ( p_what = = NOTIFICATION_TRANSLATION_CHANGED ) | | ( p_what = = NOTIFICATION_THEME_CHANGED ) ) {
for ( int i = 0 ; i < items . size ( ) ; i + + ) {
_shape ( i ) ;
}
shape_changed = true ;
update ( ) ;
}
2017-03-05 16:44:50 +01:00
if ( p_what = = NOTIFICATION_DRAW ) {
2021-07-17 23:22:52 +02:00
Ref < StyleBox > bg = get_theme_stylebox ( SNAME ( " bg " ) ) ;
2015-06-06 14:44:38 +02:00
int mw = scroll_bar - > get_minimum_size ( ) . x ;
2020-12-22 17:24:29 +01:00
scroll_bar - > set_anchor_and_offset ( SIDE_LEFT , ANCHOR_END , - mw ) ;
scroll_bar - > set_anchor_and_offset ( SIDE_RIGHT , ANCHOR_END , 0 ) ;
scroll_bar - > set_anchor_and_offset ( SIDE_TOP , ANCHOR_BEGIN , bg - > get_margin ( SIDE_TOP ) ) ;
scroll_bar - > set_anchor_and_offset ( SIDE_BOTTOM , ANCHOR_END , - bg - > get_margin ( SIDE_BOTTOM ) ) ;
2015-06-06 14:44:38 +02:00
Size2 size = get_size ( ) ;
2017-03-05 16:44:50 +01:00
int width = size . width - bg - > get_minimum_size ( ) . width ;
if ( scroll_bar - > is_visible ( ) ) {
2017-11-13 14:24:58 +01:00
width - = mw ;
2016-10-31 23:45:37 +01:00
}
2015-06-06 14:44:38 +02:00
2017-03-05 16:44:50 +01:00
draw_style_box ( bg , Rect2 ( Point2 ( ) , size ) ) ;
2015-06-06 14:44:38 +02:00
2021-07-17 23:22:52 +02:00
int hseparation = get_theme_constant ( SNAME ( " hseparation " ) ) ;
int vseparation = get_theme_constant ( SNAME ( " vseparation " ) ) ;
int icon_margin = get_theme_constant ( SNAME ( " icon_margin " ) ) ;
int line_separation = get_theme_constant ( SNAME ( " line_separation " ) ) ;
Color font_outline_color = get_theme_color ( SNAME ( " font_outline_color " ) ) ;
int outline_size = get_theme_constant ( SNAME ( " outline_size " ) ) ;
2015-06-06 14:44:38 +02:00
2021-07-17 23:22:52 +02:00
Ref < StyleBox > sbsel = has_focus ( ) ? get_theme_stylebox ( SNAME ( " selected_focus " ) ) : get_theme_stylebox ( SNAME ( " selected " ) ) ;
Ref < StyleBox > cursor = has_focus ( ) ? get_theme_stylebox ( SNAME ( " cursor " ) ) : get_theme_stylebox ( SNAME ( " cursor_unfocused " ) ) ;
2020-09-03 13:22:16 +02:00
bool rtl = is_layout_rtl ( ) ;
2015-06-06 14:44:38 +02:00
2021-07-17 23:22:52 +02:00
Color guide_color = get_theme_color ( SNAME ( " guide_color " ) ) ;
Color font_color = get_theme_color ( SNAME ( " font_color " ) ) ;
Color font_selected_color = get_theme_color ( SNAME ( " font_selected_color " ) ) ;
2015-06-06 14:44:38 +02:00
if ( has_focus ( ) ) {
2020-03-27 19:21:27 +01:00
RenderingServer : : get_singleton ( ) - > canvas_item_add_clip_ignore ( get_canvas_item ( ) , true ) ;
2021-07-17 23:22:52 +02:00
draw_style_box ( get_theme_stylebox ( SNAME ( " bg_focus " ) ) , Rect2 ( Point2 ( ) , size ) ) ;
2020-03-27 19:21:27 +01:00
RenderingServer : : get_singleton ( ) - > canvas_item_add_clip_ignore ( get_canvas_item ( ) , false ) ;
2015-06-06 14:44:38 +02:00
}
if ( shape_changed ) {
2021-02-09 18:24:36 +01:00
float max_column_width = 0.0 ;
2015-06-06 14:44:38 +02:00
//1- compute item minimum sizes
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < items . size ( ) ; i + + ) {
2015-06-06 14:44:38 +02:00
Size2 minsize ;
if ( items [ i ] . icon . is_valid ( ) ) {
2017-03-05 16:44:50 +01:00
if ( fixed_icon_size . x > 0 & & fixed_icon_size . y > 0 ) {
minsize = fixed_icon_size * icon_scale ;
2016-06-12 21:51:27 +02:00
} else {
2017-03-05 16:44:50 +01:00
minsize = items [ i ] . get_icon_size ( ) * icon_scale ;
2016-06-12 21:51:27 +02:00
}
2015-06-06 14:44:38 +02:00
2017-03-05 16:44:50 +01:00
if ( items [ i ] . text ! = " " ) {
if ( icon_mode = = ICON_MODE_TOP ) {
minsize . y + = icon_margin ;
2015-06-06 14:44:38 +02:00
} else {
2017-03-05 16:44:50 +01:00
minsize . x + = icon_margin ;
2015-06-06 14:44:38 +02:00
}
}
}
2017-03-05 16:44:50 +01:00
if ( items [ i ] . text ! = " " ) {
2021-08-21 00:22:09 +02:00
int max_width = - 1 ;
if ( fixed_column_width ) {
max_width = fixed_column_width ;
} else if ( same_column_width ) {
max_width = items [ i ] . rect_cache . size . x ;
}
items . write [ i ] . text_buf - > set_width ( max_width ) ;
2020-09-03 13:22:16 +02:00
Size2 s = items [ i ] . text_buf - > get_size ( ) ;
2015-06-06 14:44:38 +02:00
2017-03-05 16:44:50 +01:00
if ( icon_mode = = ICON_MODE_TOP ) {
minsize . x = MAX ( minsize . x , s . width ) ;
if ( max_text_lines > 0 ) {
2020-09-03 13:22:16 +02:00
minsize . y + = s . height + line_separation * max_text_lines ;
2015-06-06 14:44:38 +02:00
} else {
2017-03-05 16:44:50 +01:00
minsize . y + = s . height ;
2015-06-06 14:44:38 +02:00
}
} else {
2017-03-05 16:44:50 +01:00
minsize . y = MAX ( minsize . y , s . height ) ;
minsize . x + = s . width ;
2015-06-06 14:44:38 +02:00
}
}
2020-05-14 16:41:43 +02:00
if ( fixed_column_width > 0 ) {
2017-03-05 16:44:50 +01:00
minsize . x = fixed_column_width ;
2020-05-14 16:41:43 +02:00
}
2017-03-05 16:44:50 +01:00
max_column_width = MAX ( max_column_width , minsize . x ) ;
2017-09-27 21:44:48 +02:00
// elements need to adapt to the selected size
minsize . y + = vseparation ;
minsize . x + = hseparation ;
2018-07-25 03:11:03 +02:00
items . write [ i ] . rect_cache . size = minsize ;
items . write [ i ] . min_rect_cache . size = minsize ;
2015-06-06 14:44:38 +02:00
}
int fit_size = size . x - bg - > get_minimum_size ( ) . width - mw ;
//2-attempt best fit
current_columns = 0x7FFFFFFF ;
2020-05-14 16:41:43 +02:00
if ( max_columns > 0 ) {
2017-03-05 16:44:50 +01:00
current_columns = max_columns ;
2020-05-14 16:41:43 +02:00
}
2015-06-06 14:44:38 +02:00
2017-03-05 16:44:50 +01:00
while ( true ) {
2019-10-05 16:51:06 +02:00
//repeat until all fits
2017-03-05 16:44:50 +01:00
bool all_fit = true ;
2015-06-06 14:44:38 +02:00
Vector2 ofs ;
2017-03-05 16:44:50 +01:00
int col = 0 ;
int max_h = 0 ;
2017-01-14 18:03:38 +01:00
separators . clear ( ) ;
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < items . size ( ) ; i + + ) {
if ( current_columns > 1 & & items [ i ] . rect_cache . size . width + ofs . x > fit_size ) {
2015-06-06 14:44:38 +02:00
//went past
2017-03-05 16:44:50 +01:00
current_columns = MAX ( col , 1 ) ;
all_fit = false ;
2015-06-06 14:44:38 +02:00
break ;
}
2020-05-14 16:41:43 +02:00
if ( same_column_width ) {
2018-07-25 03:11:03 +02:00
items . write [ i ] . rect_cache . size . x = max_column_width ;
2020-05-14 16:41:43 +02:00
}
2018-07-25 03:11:03 +02:00
items . write [ i ] . rect_cache . position = ofs ;
2017-03-05 16:44:50 +01:00
max_h = MAX ( max_h , items [ i ] . rect_cache . size . y ) ;
ofs . x + = items [ i ] . rect_cache . size . x + hseparation ;
2015-06-06 14:44:38 +02:00
col + + ;
2017-03-05 16:44:50 +01:00
if ( col = = current_columns ) {
2020-05-14 16:41:43 +02:00
if ( i < items . size ( ) - 1 ) {
2017-03-05 16:44:50 +01:00
separators . push_back ( ofs . y + max_h + vseparation / 2 ) ;
2020-05-14 16:41:43 +02:00
}
2016-07-19 20:50:01 +02:00
2017-03-05 16:44:50 +01:00
for ( int j = i ; j > = 0 & & col > 0 ; j - - , col - - ) {
2018-07-25 03:11:03 +02:00
items . write [ j ] . rect_cache . size . y = max_h ;
2016-05-27 21:42:51 +02:00
}
2016-07-19 20:50:01 +02:00
2017-03-05 16:44:50 +01:00
ofs . x = 0 ;
ofs . y + = max_h + vseparation ;
col = 0 ;
max_h = 0 ;
2015-06-06 14:44:38 +02:00
}
}
2017-03-05 16:44:50 +01:00
for ( int j = items . size ( ) - 1 ; j > = 0 & & col > 0 ; j - - , col - - ) {
2018-07-25 03:11:03 +02:00
items . write [ j ] . rect_cache . size . y = max_h ;
2016-05-27 21:42:51 +02:00
}
2015-06-06 14:44:38 +02:00
if ( all_fit ) {
2019-11-26 10:25:41 +01:00
float page = MAX ( 0 , size . height - bg - > get_minimum_size ( ) . height ) ;
2017-03-05 16:44:50 +01:00
float max = MAX ( page , ofs . y + max_h ) ;
2020-05-14 16:41:43 +02:00
if ( auto_height ) {
2017-07-21 08:17:06 +02:00
auto_height_value = ofs . y + max_h + bg - > get_minimum_size ( ) . height ;
2020-05-14 16:41:43 +02:00
}
2019-12-08 20:11:37 +01:00
scroll_bar - > set_max ( max ) ;
scroll_bar - > set_page ( page ) ;
2017-03-05 16:44:50 +01:00
if ( max < = page ) {
2017-01-04 05:16:14 +01:00
scroll_bar - > set_value ( 0 ) ;
2015-06-06 14:44:38 +02:00
scroll_bar - > hide ( ) ;
} else {
scroll_bar - > show ( ) ;
2017-12-17 23:16:11 +01:00
2020-05-14 16:41:43 +02:00
if ( do_autoscroll_to_bottom ) {
2017-12-17 23:16:11 +01:00
scroll_bar - > set_value ( max ) ;
2020-05-14 16:41:43 +02:00
}
2015-06-06 14:44:38 +02:00
}
break ;
}
}
2018-07-01 02:36:54 +02:00
minimum_size_changed ( ) ;
2017-03-05 16:44:50 +01:00
shape_changed = false ;
2015-06-06 14:44:38 +02:00
}
2016-09-16 17:25:07 +02:00
//ensure_selected_visible needs to be checked before we draw the list.
2020-01-14 20:17:48 +01:00
if ( ensure_selected_visible & & current > = 0 & & current < items . size ( ) ) {
2016-09-16 17:25:07 +02:00
Rect2 r = items [ current ] . rect_cache ;
2017-01-04 05:16:14 +01:00
int from = scroll_bar - > get_value ( ) ;
2016-09-16 17:25:07 +02:00
int to = from + scroll_bar - > get_page ( ) ;
2017-06-04 00:25:13 +02:00
if ( r . position . y < from ) {
scroll_bar - > set_value ( r . position . y ) ;
} else if ( r . position . y + r . size . y > to ) {
scroll_bar - > set_value ( r . position . y + r . size . y - ( to - from ) ) ;
2016-09-16 17:25:07 +02:00
}
}
2017-03-05 16:44:50 +01:00
ensure_selected_visible = false ;
2015-06-06 14:44:38 +02:00
Vector2 base_ofs = bg - > get_offset ( ) ;
2017-03-05 16:44:50 +01:00
base_ofs . y - = int ( scroll_bar - > get_value ( ) ) ;
2015-06-06 14:44:38 +02:00
2018-01-03 21:11:50 +01:00
const Rect2 clip ( - base_ofs , size ) ; // visible frame, don't need to draw outside of there
int first_item_visible ;
{
// do a binary search to find the first item whose rect reaches below clip.position.y
int lo = 0 ;
int hi = items . size ( ) ;
while ( lo < hi ) {
const int mid = ( lo + hi ) / 2 ;
const Rect2 & rcache = items [ mid ] . rect_cache ;
if ( rcache . position . y + rcache . size . y < clip . position . y ) {
lo = mid + 1 ;
} else {
hi = mid ;
}
}
// we might have ended up with column 2, or 3, ..., so let's find the first column
while ( lo > 0 & & items [ lo - 1 ] . rect_cache . position . y = = items [ lo ] . rect_cache . position . y ) {
lo - = 1 ;
}
first_item_visible = lo ;
}
2015-06-06 14:44:38 +02:00
2018-01-03 21:11:50 +01:00
for ( int i = first_item_visible ; i < items . size ( ) ; i + + ) {
2015-06-06 14:44:38 +02:00
Rect2 rcache = items [ i ] . rect_cache ;
2020-05-14 16:41:43 +02:00
if ( rcache . position . y > clip . position . y + clip . size . y ) {
2018-01-03 21:11:50 +01:00
break ; // done
2020-05-14 16:41:43 +02:00
}
2018-01-03 21:11:50 +01:00
2020-05-14 16:41:43 +02:00
if ( ! clip . intersects ( rcache ) ) {
2015-06-06 14:44:38 +02:00
continue ;
2020-05-14 16:41:43 +02:00
}
2015-06-06 14:44:38 +02:00
2017-03-05 16:44:50 +01:00
if ( current_columns = = 1 ) {
2017-06-04 00:25:13 +02:00
rcache . size . width = width - rcache . position . x ;
2015-06-06 14:44:38 +02:00
}
2016-01-22 00:21:44 +01:00
if ( items [ i ] . selected ) {
2017-06-05 02:58:29 +02:00
Rect2 r = rcache ;
r . position + = base_ofs ;
2017-09-27 21:44:48 +02:00
r . position . y - = vseparation / 2 ;
r . size . y + = vseparation ;
r . position . x - = hseparation / 2 ;
r . size . x + = hseparation ;
2017-06-05 02:58:29 +02:00
2020-09-03 13:22:16 +02:00
if ( rtl ) {
r . position . x = size . width - r . position . x - r . size . x ;
}
2017-03-05 16:44:50 +01:00
draw_style_box ( sbsel , r ) ;
2016-01-22 00:21:44 +01:00
}
2017-03-05 16:44:50 +01:00
if ( items [ i ] . custom_bg . a > 0.001 ) {
2017-06-05 02:58:29 +02:00
Rect2 r = rcache ;
r . position + = base_ofs ;
// Size rect to make the align the temperature colors
r . position . y - = vseparation / 2 ;
r . size . y + = vseparation ;
2017-09-27 21:44:48 +02:00
r . position . x - = hseparation / 2 ;
r . size . x + = hseparation ;
2020-09-03 13:22:16 +02:00
if ( rtl ) {
r . position . x = size . width - r . position . x - r . size . x ;
}
2017-03-05 16:44:50 +01:00
draw_rect ( r , items [ i ] . custom_bg ) ;
2015-06-06 14:44:38 +02:00
}
Vector2 text_ofs ;
if ( items [ i ] . icon . is_valid ( ) ) {
2016-06-12 21:51:27 +02:00
Size2 icon_size ;
//= _adjust_to_max_size(items[i].get_icon_size(),fixed_icon_size) * icon_scale;
2017-03-05 16:44:50 +01:00
if ( fixed_icon_size . x > 0 & & fixed_icon_size . y > 0 ) {
icon_size = fixed_icon_size * icon_scale ;
2016-06-12 21:51:27 +02:00
} else {
2017-03-05 16:44:50 +01:00
icon_size = items [ i ] . get_icon_size ( ) * icon_scale ;
2015-06-06 14:44:38 +02:00
}
2016-06-12 21:51:27 +02:00
Vector2 icon_ofs ;
2017-06-04 00:25:13 +02:00
Point2 pos = items [ i ] . rect_cache . position + icon_ofs + base_ofs ;
2016-03-13 16:23:49 +01:00
2017-03-05 16:44:50 +01:00
if ( icon_mode = = ICON_MODE_TOP ) {
pos . x + = Math : : floor ( ( items [ i ] . rect_cache . size . width - icon_size . width ) / 2 ) ;
2021-08-21 00:22:09 +02:00
pos . y + = icon_margin ;
text_ofs . y = icon_size . height + icon_margin * 2 ;
2015-06-06 14:44:38 +02:00
} else {
2017-03-05 16:44:50 +01:00
pos . y + = Math : : floor ( ( items [ i ] . rect_cache . size . height - icon_size . height ) / 2 ) ;
2016-06-12 21:51:27 +02:00
text_ofs . x = icon_size . width + icon_margin ;
}
2017-03-05 16:44:50 +01:00
Rect2 draw_rect = Rect2 ( pos , icon_size ) ;
2016-06-12 21:51:27 +02:00
2017-03-05 16:44:50 +01:00
if ( fixed_icon_size . x > 0 & & fixed_icon_size . y > 0 ) {
Rect2 adj = _adjust_to_max_size ( items [ i ] . get_icon_size ( ) * icon_scale , icon_size ) ;
2017-06-04 00:25:13 +02:00
draw_rect . position + = adj . position ;
2017-03-05 16:44:50 +01:00
draw_rect . size = adj . size ;
2015-06-06 14:44:38 +02:00
}
2016-03-13 16:23:49 +01:00
2018-03-11 15:59:50 +01:00
Color modulate = items [ i ] . icon_modulate ;
2020-05-14 16:41:43 +02:00
if ( items [ i ] . disabled ) {
2017-03-05 16:44:50 +01:00
modulate . a * = 0.5 ;
2020-05-14 16:41:43 +02:00
}
2016-07-21 23:24:56 +02:00
2019-02-13 09:23:29 +01:00
// If the icon is transposed, we have to switch the size so that it is drawn correctly
2018-10-29 17:16:18 +01:00
if ( items [ i ] . icon_transposed ) {
Size2 size_tmp = draw_rect . size ;
draw_rect . size . x = size_tmp . y ;
draw_rect . size . y = size_tmp . x ;
}
2018-11-07 18:29:24 +01:00
Rect2 region = ( items [ i ] . icon_region . size . x = = 0 | | items [ i ] . icon_region . size . y = = 0 ) ? Rect2 ( Vector2 ( ) , items [ i ] . icon - > get_size ( ) ) : Rect2 ( items [ i ] . icon_region ) ;
2020-09-03 13:22:16 +02:00
if ( rtl ) {
draw_rect . position . x = size . width - draw_rect . position . x - draw_rect . size . x ;
}
2018-11-07 18:29:24 +01:00
draw_texture_rect_region ( items [ i ] . icon , draw_rect , region , modulate , items [ i ] . icon_transposed ) ;
2015-06-06 14:44:38 +02:00
}
if ( items [ i ] . tag_icon . is_valid ( ) ) {
2020-09-03 13:22:16 +02:00
Point2 draw_pos = items [ i ] . rect_cache . position ;
if ( rtl ) {
draw_pos . x = size . width - draw_pos . x - items [ i ] . tag_icon - > get_width ( ) ;
}
draw_texture ( items [ i ] . tag_icon , draw_pos + base_ofs ) ;
2015-06-06 14:44:38 +02:00
}
2017-03-05 16:44:50 +01:00
if ( items [ i ] . text ! = " " ) {
int max_len = - 1 ;
2015-06-06 14:44:38 +02:00
2020-09-03 13:22:16 +02:00
Vector2 size2 = items [ i ] . text_buf - > get_size ( ) ;
2020-05-14 16:41:43 +02:00
if ( fixed_column_width ) {
2017-03-05 16:44:50 +01:00
max_len = fixed_column_width ;
2020-05-14 16:41:43 +02:00
} else if ( same_column_width ) {
2017-03-05 16:44:50 +01:00
max_len = items [ i ] . rect_cache . size . x ;
2020-05-14 16:41:43 +02:00
} else {
2019-02-12 21:10:08 +01:00
max_len = size2 . x ;
2020-05-14 16:41:43 +02:00
}
2015-06-06 14:44:38 +02:00
2020-12-08 14:11:45 +01:00
Color modulate = items [ i ] . selected ? font_selected_color : ( items [ i ] . custom_fg ! = Color ( ) ? items [ i ] . custom_fg : font_color ) ;
2020-05-14 16:41:43 +02:00
if ( items [ i ] . disabled ) {
2017-03-05 16:44:50 +01:00
modulate . a * = 0.5 ;
2020-05-14 16:41:43 +02:00
}
2016-07-21 23:24:56 +02:00
2017-03-05 16:44:50 +01:00
if ( icon_mode = = ICON_MODE_TOP & & max_text_lines > 0 ) {
text_ofs + = base_ofs ;
2017-06-04 00:25:13 +02:00
text_ofs + = items [ i ] . rect_cache . position ;
2015-06-06 14:44:38 +02:00
2020-09-03 13:22:16 +02:00
if ( rtl ) {
text_ofs . x = size . width - text_ofs . x - max_len ;
2015-06-06 14:44:38 +02:00
}
2020-09-03 13:22:16 +02:00
items . write [ i ] . text_buf - > set_align ( HALIGN_CENTER ) ;
2020-12-25 22:45:28 +01:00
if ( outline_size > 0 & & font_outline_color . a > 0 ) {
items [ i ] . text_buf - > draw_outline ( get_canvas_item ( ) , text_ofs , outline_size , font_outline_color ) ;
}
2020-09-03 13:22:16 +02:00
items [ i ] . text_buf - > draw ( get_canvas_item ( ) , text_ofs , modulate ) ;
2015-06-06 14:44:38 +02:00
} else {
2020-05-14 16:41:43 +02:00
if ( fixed_column_width > 0 ) {
2019-02-12 21:10:08 +01:00
size2 . x = MIN ( size2 . x , fixed_column_width ) ;
2020-05-14 16:41:43 +02:00
}
2015-06-06 14:44:38 +02:00
2017-03-05 16:44:50 +01:00
if ( icon_mode = = ICON_MODE_TOP ) {
2019-02-12 21:10:08 +01:00
text_ofs . x + = ( items [ i ] . rect_cache . size . width - size2 . x ) / 2 ;
2015-06-06 14:44:38 +02:00
} else {
2019-02-12 21:10:08 +01:00
text_ofs . y + = ( items [ i ] . rect_cache . size . height - size2 . y ) / 2 ;
2015-06-06 14:44:38 +02:00
}
2017-03-05 16:44:50 +01:00
text_ofs + = base_ofs ;
2017-06-04 00:25:13 +02:00
text_ofs + = items [ i ] . rect_cache . position ;
2015-06-06 14:44:38 +02:00
2020-09-03 13:22:16 +02:00
if ( rtl ) {
text_ofs . x = size . width - text_ofs . x - max_len ;
}
items . write [ i ] . text_buf - > set_width ( max_len ) ;
if ( rtl ) {
items . write [ i ] . text_buf - > set_align ( HALIGN_RIGHT ) ;
} else {
items . write [ i ] . text_buf - > set_align ( HALIGN_LEFT ) ;
}
2020-12-25 22:45:28 +01:00
if ( outline_size > 0 & & font_outline_color . a > 0 ) {
items [ i ] . text_buf - > draw_outline ( get_canvas_item ( ) , text_ofs , outline_size , font_outline_color ) ;
}
2020-09-03 13:22:16 +02:00
items [ i ] . text_buf - > draw ( get_canvas_item ( ) , text_ofs , modulate ) ;
2015-06-06 14:44:38 +02:00
}
}
2017-03-05 16:44:50 +01:00
if ( select_mode = = SELECT_MULTI & & i = = current ) {
Rect2 r = rcache ;
2017-06-04 00:25:13 +02:00
r . position + = base_ofs ;
2017-09-27 21:44:48 +02:00
r . position . y - = vseparation / 2 ;
r . size . y + = vseparation ;
r . position . x - = hseparation / 2 ;
r . size . x + = hseparation ;
2020-09-03 13:22:16 +02:00
if ( rtl ) {
r . position . x = size . width - r . position . x - r . size . x ;
}
2017-03-05 16:44:50 +01:00
draw_style_box ( cursor , r ) ;
2015-06-06 14:44:38 +02:00
}
}
2018-01-03 21:11:50 +01:00
int first_visible_separator = 0 ;
{
// do a binary search to find the first separator that is below clip_position.y
int lo = 0 ;
int hi = separators . size ( ) ;
while ( lo < hi ) {
const int mid = ( lo + hi ) / 2 ;
if ( separators [ mid ] < clip . position . y ) {
lo = mid + 1 ;
} else {
hi = mid ;
}
}
first_visible_separator = lo ;
}
for ( int i = first_visible_separator ; i < separators . size ( ) ; i + + ) {
2020-05-14 16:41:43 +02:00
if ( separators [ i ] > clip . position . y + clip . size . y ) {
2018-01-03 21:11:50 +01:00
break ; // done
2020-05-14 16:41:43 +02:00
}
2018-01-03 21:11:50 +01:00
const int y = base_ofs . y + separators [ i ] ;
2020-12-22 17:24:29 +01:00
draw_line ( Vector2 ( bg - > get_margin ( SIDE_LEFT ) , y ) , Vector2 ( width , y ) , guide_color ) ;
2015-06-06 14:44:38 +02:00
}
}
}
void ItemList : : _scroll_changed ( double ) {
update ( ) ;
}
2017-09-10 15:37:49 +02:00
int ItemList : : get_item_at_position ( const Point2 & p_pos , bool p_exact ) const {
2017-03-05 16:44:50 +01:00
Vector2 pos = p_pos ;
2021-07-17 23:22:52 +02:00
Ref < StyleBox > bg = get_theme_stylebox ( SNAME ( " bg " ) ) ;
2017-03-05 16:44:50 +01:00
pos - = bg - > get_offset ( ) ;
pos . y + = scroll_bar - > get_value ( ) ;
2015-06-06 14:44:38 +02:00
2020-09-03 13:22:16 +02:00
if ( is_layout_rtl ( ) ) {
pos . x = get_size ( ) . width - pos . x ;
}
2015-06-06 14:44:38 +02:00
int closest = - 1 ;
2017-03-05 16:44:50 +01:00
int closest_dist = 0x7FFFFFFF ;
2015-06-06 14:44:38 +02:00
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < items . size ( ) ; i + + ) {
2015-06-06 14:44:38 +02:00
Rect2 rc = items [ i ] . rect_cache ;
2017-03-05 16:44:50 +01:00
if ( i % current_columns = = current_columns - 1 ) {
2019-06-01 14:42:13 +02:00
rc . size . width = get_size ( ) . width - rc . position . x ; //make sure you can still select the last item when clicking past the column
2015-06-06 14:44:38 +02:00
}
if ( rc . has_point ( pos ) ) {
2017-03-05 16:44:50 +01:00
closest = i ;
2015-06-06 14:44:38 +02:00
break ;
}
float dist = rc . distance_to ( pos ) ;
2017-03-05 16:44:50 +01:00
if ( ! p_exact & & dist < closest_dist ) {
closest = i ;
closest_dist = dist ;
2015-06-06 14:44:38 +02:00
}
}
2016-05-11 16:46:08 +02:00
return closest ;
}
2017-03-05 16:44:50 +01:00
bool ItemList : : is_pos_at_end_of_items ( const Point2 & p_pos ) const {
2020-12-15 13:04:21 +01:00
if ( items . is_empty ( ) ) {
2017-02-20 03:19:30 +01:00
return true ;
2020-05-14 16:41:43 +02:00
}
2017-02-20 03:19:30 +01:00
2017-03-05 16:44:50 +01:00
Vector2 pos = p_pos ;
2021-07-17 23:22:52 +02:00
Ref < StyleBox > bg = get_theme_stylebox ( SNAME ( " bg " ) ) ;
2017-03-05 16:44:50 +01:00
pos - = bg - > get_offset ( ) ;
pos . y + = scroll_bar - > get_value ( ) ;
2017-02-20 03:19:30 +01:00
2020-09-03 13:22:16 +02:00
if ( is_layout_rtl ( ) ) {
pos . x = get_size ( ) . width - pos . x ;
}
2017-03-05 16:44:50 +01:00
Rect2 endrect = items [ items . size ( ) - 1 ] . rect_cache ;
2017-06-04 00:25:13 +02:00
return ( pos . y > endrect . position . y + endrect . size . y ) ;
2017-02-20 03:19:30 +01:00
}
2017-03-05 16:44:50 +01:00
String ItemList : : get_tooltip ( const Point2 & p_pos ) const {
2018-01-02 04:46:32 +01:00
int closest = get_item_at_position ( p_pos , true ) ;
2016-05-11 16:46:08 +02:00
2017-03-05 16:44:50 +01:00
if ( closest ! = - 1 ) {
2016-09-07 17:21:20 +02:00
if ( ! items [ closest ] . tooltip_enabled ) {
return " " ;
}
2017-03-05 16:44:50 +01:00
if ( items [ closest ] . tooltip ! = " " ) {
2015-06-06 14:44:38 +02:00
return items [ closest ] . tooltip ;
}
2017-03-05 16:44:50 +01:00
if ( items [ closest ] . text ! = " " ) {
2015-06-06 14:44:38 +02:00
return items [ closest ] . text ;
}
}
return Control : : get_tooltip ( p_pos ) ;
}
2015-06-22 05:03:19 +02:00
void ItemList : : sort_items_by_text ( ) {
items . sort ( ) ;
update ( ) ;
2017-03-05 16:44:50 +01:00
shape_changed = true ;
2016-07-22 07:45:52 +02:00
2017-03-05 16:44:50 +01:00
if ( select_mode = = SELECT_SINGLE ) {
for ( int i = 0 ; i < items . size ( ) ; i + + ) {
2015-06-22 05:03:19 +02:00
if ( items [ i ] . selected ) {
select ( i ) ;
return ;
}
}
}
}
2017-03-05 16:44:50 +01:00
int ItemList : : find_metadata ( const Variant & p_metadata ) const {
for ( int i = 0 ; i < items . size ( ) ; i + + ) {
if ( items [ i ] . metadata = = p_metadata ) {
2015-06-22 05:03:19 +02:00
return i ;
}
}
return - 1 ;
}
2015-06-06 14:44:38 +02:00
2016-05-16 01:25:51 +02:00
void ItemList : : set_allow_rmb_select ( bool p_allow ) {
2017-03-05 16:44:50 +01:00
allow_rmb_select = p_allow ;
2016-05-16 01:25:51 +02:00
}
bool ItemList : : get_allow_rmb_select ( ) const {
return allow_rmb_select ;
}
2018-02-14 04:24:57 +01:00
void ItemList : : set_allow_reselect ( bool p_allow ) {
allow_reselect = p_allow ;
}
bool ItemList : : get_allow_reselect ( ) const {
return allow_reselect ;
}
2016-05-27 18:54:46 +02:00
void ItemList : : set_icon_scale ( real_t p_scale ) {
icon_scale = p_scale ;
2016-05-24 19:09:58 +02:00
}
2016-05-27 18:54:46 +02:00
real_t ItemList : : get_icon_scale ( ) const {
return icon_scale ;
2016-05-24 19:09:58 +02:00
}
2016-06-28 19:09:17 +02:00
Vector < int > ItemList : : get_selected_items ( ) {
Vector < int > selected ;
for ( int i = 0 ; i < items . size ( ) ; i + + ) {
if ( items [ i ] . selected ) {
selected . push_back ( i ) ;
if ( this - > select_mode = = SELECT_SINGLE ) {
break ;
}
}
}
return selected ;
}
2017-11-24 14:39:02 +01:00
bool ItemList : : is_anything_selected ( ) {
for ( int i = 0 ; i < items . size ( ) ; i + + ) {
2020-05-14 16:41:43 +02:00
if ( items [ i ] . selected ) {
2017-11-24 14:39:02 +01:00
return true ;
2020-05-14 16:41:43 +02:00
}
2017-11-24 14:39:02 +01:00
}
return false ;
}
2017-07-04 13:38:56 +02:00
void ItemList : : _set_items ( const Array & p_items ) {
ERR_FAIL_COND ( p_items . size ( ) % 3 ) ;
clear ( ) ;
for ( int i = 0 ; i < p_items . size ( ) ; i + = 3 ) {
String text = p_items [ i + 0 ] ;
2019-06-11 20:43:37 +02:00
Ref < Texture2D > icon = p_items [ i + 1 ] ;
2017-07-04 13:38:56 +02:00
bool disabled = p_items [ i + 2 ] ;
int idx = get_item_count ( ) ;
add_item ( text , icon ) ;
set_item_disabled ( idx , disabled ) ;
}
}
Array ItemList : : _get_items ( ) const {
Array items ;
for ( int i = 0 ; i < get_item_count ( ) ; i + + ) {
items . push_back ( get_item_text ( i ) ) ;
items . push_back ( get_item_icon ( i ) ) ;
items . push_back ( is_item_disabled ( i ) ) ;
}
return items ;
}
2017-07-21 08:17:06 +02:00
Size2 ItemList : : get_minimum_size ( ) const {
if ( auto_height ) {
return Size2 ( 0 , auto_height_value ) ;
}
return Size2 ( ) ;
}
2017-12-17 23:16:11 +01:00
void ItemList : : set_autoscroll_to_bottom ( const bool p_enable ) {
do_autoscroll_to_bottom = p_enable ;
}
2017-07-21 08:17:06 +02:00
void ItemList : : set_auto_height ( bool p_enable ) {
auto_height = p_enable ;
shape_changed = true ;
update ( ) ;
}
bool ItemList : : has_auto_height ( ) const {
return auto_height ;
}
2021-08-21 00:22:09 +02:00
void ItemList : : set_text_overrun_behavior ( TextParagraph : : OverrunBehavior p_behavior ) {
if ( text_overrun_behavior ! = p_behavior ) {
text_overrun_behavior = p_behavior ;
for ( int i = 0 ; i < items . size ( ) ; i + + ) {
items . write [ i ] . text_buf - > set_text_overrun_behavior ( p_behavior ) ;
}
shape_changed = true ;
update ( ) ;
}
}
TextParagraph : : OverrunBehavior ItemList : : get_text_overrun_behavior ( ) const {
return text_overrun_behavior ;
}
2017-03-05 16:44:50 +01:00
void ItemList : : _bind_methods ( ) {
2017-08-09 13:19:41 +02:00
ClassDB : : bind_method ( D_METHOD ( " add_item " , " text " , " icon " , " selectable " ) , & ItemList : : add_item , DEFVAL ( Variant ( ) ) , DEFVAL ( true ) ) ;
ClassDB : : bind_method ( D_METHOD ( " add_icon_item " , " icon " , " selectable " ) , & ItemList : : add_icon_item , DEFVAL ( true ) ) ;
2015-06-06 14:44:38 +02:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_item_text " , " idx " , " text " ) , & ItemList : : set_item_text ) ;
ClassDB : : bind_method ( D_METHOD ( " get_item_text " , " idx " ) , & ItemList : : get_item_text ) ;
2015-06-06 14:44:38 +02:00
2017-08-09 13:19:41 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_item_icon " , " idx " , " icon " ) , & ItemList : : set_item_icon ) ;
ClassDB : : bind_method ( D_METHOD ( " get_item_icon " , " idx " ) , & ItemList : : get_item_icon ) ;
2015-06-06 14:44:38 +02:00
2020-09-03 13:22:16 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_item_text_direction " , " idx " , " direction " ) , & ItemList : : set_item_text_direction ) ;
ClassDB : : bind_method ( D_METHOD ( " get_item_text_direction " , " idx " ) , & ItemList : : get_item_text_direction ) ;
ClassDB : : bind_method ( D_METHOD ( " set_item_opentype_feature " , " idx " , " tag " , " value " ) , & ItemList : : set_item_opentype_feature ) ;
ClassDB : : bind_method ( D_METHOD ( " get_item_opentype_feature " , " idx " , " tag " ) , & ItemList : : get_item_opentype_feature ) ;
ClassDB : : bind_method ( D_METHOD ( " clear_item_opentype_features " , " idx " ) , & ItemList : : clear_item_opentype_features ) ;
ClassDB : : bind_method ( D_METHOD ( " set_item_language " , " idx " , " language " ) , & ItemList : : set_item_language ) ;
ClassDB : : bind_method ( D_METHOD ( " get_item_language " , " idx " ) , & ItemList : : get_item_language ) ;
2019-12-26 04:27:28 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_item_icon_transposed " , " idx " , " transposed " ) , & ItemList : : set_item_icon_transposed ) ;
2018-10-29 17:16:18 +01:00
ClassDB : : bind_method ( D_METHOD ( " is_item_icon_transposed " , " idx " ) , & ItemList : : is_item_icon_transposed ) ;
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_item_icon_region " , " idx " , " rect " ) , & ItemList : : set_item_icon_region ) ;
ClassDB : : bind_method ( D_METHOD ( " get_item_icon_region " , " idx " ) , & ItemList : : get_item_icon_region ) ;
2016-03-13 16:23:49 +01:00
2018-03-11 15:59:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_item_icon_modulate " , " idx " , " modulate " ) , & ItemList : : set_item_icon_modulate ) ;
ClassDB : : bind_method ( D_METHOD ( " get_item_icon_modulate " , " idx " ) , & ItemList : : get_item_icon_modulate ) ;
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_item_selectable " , " idx " , " selectable " ) , & ItemList : : set_item_selectable ) ;
ClassDB : : bind_method ( D_METHOD ( " is_item_selectable " , " idx " ) , & ItemList : : is_item_selectable ) ;
2015-06-06 14:44:38 +02:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_item_disabled " , " idx " , " disabled " ) , & ItemList : : set_item_disabled ) ;
ClassDB : : bind_method ( D_METHOD ( " is_item_disabled " , " idx " ) , & ItemList : : is_item_disabled ) ;
2015-06-06 14:44:38 +02:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_item_metadata " , " idx " , " metadata " ) , & ItemList : : set_item_metadata ) ;
2017-08-09 13:19:41 +02:00
ClassDB : : bind_method ( D_METHOD ( " get_item_metadata " , " idx " ) , & ItemList : : get_item_metadata ) ;
2015-06-22 05:03:19 +02:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_item_custom_bg_color " , " idx " , " custom_bg_color " ) , & ItemList : : set_item_custom_bg_color ) ;
ClassDB : : bind_method ( D_METHOD ( " get_item_custom_bg_color " , " idx " ) , & ItemList : : get_item_custom_bg_color ) ;
2015-06-22 05:03:19 +02:00
2018-08-17 13:46:33 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_item_custom_fg_color " , " idx " , " custom_fg_color " ) , & ItemList : : set_item_custom_fg_color ) ;
ClassDB : : bind_method ( D_METHOD ( " get_item_custom_fg_color " , " idx " ) , & ItemList : : get_item_custom_fg_color ) ;
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_item_tooltip_enabled " , " idx " , " enable " ) , & ItemList : : set_item_tooltip_enabled ) ;
ClassDB : : bind_method ( D_METHOD ( " is_item_tooltip_enabled " , " idx " ) , & ItemList : : is_item_tooltip_enabled ) ;
2016-09-07 17:21:20 +02:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_item_tooltip " , " idx " , " tooltip " ) , & ItemList : : set_item_tooltip ) ;
ClassDB : : bind_method ( D_METHOD ( " get_item_tooltip " , " idx " ) , & ItemList : : get_item_tooltip ) ;
2015-06-06 14:44:38 +02:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " select " , " idx " , " single " ) , & ItemList : : select , DEFVAL ( true ) ) ;
2020-12-21 11:26:41 +01:00
ClassDB : : bind_method ( D_METHOD ( " deselect " , " idx " ) , & ItemList : : deselect ) ;
ClassDB : : bind_method ( D_METHOD ( " deselect_all " ) , & ItemList : : deselect_all ) ;
2018-03-13 16:46:25 +01:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " is_selected " , " idx " ) , & ItemList : : is_selected ) ;
ClassDB : : bind_method ( D_METHOD ( " get_selected_items " ) , & ItemList : : get_selected_items ) ;
2015-06-06 14:44:38 +02:00
2018-03-23 18:57:58 +01:00
ClassDB : : bind_method ( D_METHOD ( " move_item " , " from_idx " , " to_idx " ) , & ItemList : : move_item ) ;
2018-03-13 15:19:04 +01:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " get_item_count " ) , & ItemList : : get_item_count ) ;
ClassDB : : bind_method ( D_METHOD ( " remove_item " , " idx " ) , & ItemList : : remove_item ) ;
2015-06-06 14:44:38 +02:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " clear " ) , & ItemList : : clear ) ;
ClassDB : : bind_method ( D_METHOD ( " sort_items_by_text " ) , & ItemList : : sort_items_by_text ) ;
2015-06-06 14:44:38 +02:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_fixed_column_width " , " width " ) , & ItemList : : set_fixed_column_width ) ;
ClassDB : : bind_method ( D_METHOD ( " get_fixed_column_width " ) , & ItemList : : get_fixed_column_width ) ;
2015-06-06 14:44:38 +02:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_same_column_width " , " enable " ) , & ItemList : : set_same_column_width ) ;
ClassDB : : bind_method ( D_METHOD ( " is_same_column_width " ) , & ItemList : : is_same_column_width ) ;
2016-05-27 21:42:51 +02:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_max_text_lines " , " lines " ) , & ItemList : : set_max_text_lines ) ;
ClassDB : : bind_method ( D_METHOD ( " get_max_text_lines " ) , & ItemList : : get_max_text_lines ) ;
2015-06-06 14:44:38 +02:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_max_columns " , " amount " ) , & ItemList : : set_max_columns ) ;
ClassDB : : bind_method ( D_METHOD ( " get_max_columns " ) , & ItemList : : get_max_columns ) ;
2015-06-06 14:44:38 +02:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_select_mode " , " mode " ) , & ItemList : : set_select_mode ) ;
ClassDB : : bind_method ( D_METHOD ( " get_select_mode " ) , & ItemList : : get_select_mode ) ;
2015-06-06 14:44:38 +02:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_icon_mode " , " mode " ) , & ItemList : : set_icon_mode ) ;
ClassDB : : bind_method ( D_METHOD ( " get_icon_mode " ) , & ItemList : : get_icon_mode ) ;
2015-06-06 14:44:38 +02:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_fixed_icon_size " , " size " ) , & ItemList : : set_fixed_icon_size ) ;
ClassDB : : bind_method ( D_METHOD ( " get_fixed_icon_size " ) , & ItemList : : get_fixed_icon_size ) ;
2015-06-06 14:44:38 +02:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_icon_scale " , " scale " ) , & ItemList : : set_icon_scale ) ;
ClassDB : : bind_method ( D_METHOD ( " get_icon_scale " ) , & ItemList : : get_icon_scale ) ;
2016-05-15 04:48:23 +02:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_allow_rmb_select " , " allow " ) , & ItemList : : set_allow_rmb_select ) ;
ClassDB : : bind_method ( D_METHOD ( " get_allow_rmb_select " ) , & ItemList : : get_allow_rmb_select ) ;
2016-05-24 19:09:58 +02:00
2018-02-14 04:24:57 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_allow_reselect " , " allow " ) , & ItemList : : set_allow_reselect ) ;
ClassDB : : bind_method ( D_METHOD ( " get_allow_reselect " ) , & ItemList : : get_allow_reselect ) ;
2017-07-21 08:17:06 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_auto_height " , " enable " ) , & ItemList : : set_auto_height ) ;
ClassDB : : bind_method ( D_METHOD ( " has_auto_height " ) , & ItemList : : has_auto_height ) ;
2018-03-11 03:01:16 +01:00
ClassDB : : bind_method ( D_METHOD ( " is_anything_selected " ) , & ItemList : : is_anything_selected ) ;
2017-09-10 15:37:49 +02:00
ClassDB : : bind_method ( D_METHOD ( " get_item_at_position " , " position " , " exact " ) , & ItemList : : get_item_at_position , DEFVAL ( false ) ) ;
2016-05-16 01:25:51 +02:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " ensure_current_is_visible " ) , & ItemList : : ensure_current_is_visible ) ;
2016-05-11 16:46:08 +02:00
2017-08-09 13:19:41 +02:00
ClassDB : : bind_method ( D_METHOD ( " get_v_scroll " ) , & ItemList : : get_v_scroll ) ;
2015-06-06 14:44:38 +02:00
2017-03-05 16:44:50 +01:00
ClassDB : : bind_method ( D_METHOD ( " _gui_input " ) , & ItemList : : _gui_input ) ;
2016-09-09 16:20:57 +02:00
2017-07-04 13:38:56 +02:00
ClassDB : : bind_method ( D_METHOD ( " _set_items " ) , & ItemList : : _set_items ) ;
ClassDB : : bind_method ( D_METHOD ( " _get_items " ) , & ItemList : : _get_items ) ;
2021-08-21 00:22:09 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_text_overrun_behavior " , " overrun_behavior " ) , & ItemList : : set_text_overrun_behavior ) ;
ClassDB : : bind_method ( D_METHOD ( " get_text_overrun_behavior " ) , & ItemList : : get_text_overrun_behavior ) ;
2018-01-11 23:35:12 +01:00
ADD_PROPERTY ( PropertyInfo ( Variant : : ARRAY , " items " , PROPERTY_HINT_NONE , " " , PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL ) , " _set_items " , " _get_items " ) ;
2017-07-04 13:38:56 +02:00
ADD_PROPERTY ( PropertyInfo ( Variant : : INT , " select_mode " , PROPERTY_HINT_ENUM , " Single,Multi " ) , " set_select_mode " , " get_select_mode " ) ;
2018-02-14 04:24:57 +01:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " allow_reselect " ) , " set_allow_reselect " , " get_allow_reselect " ) ;
2018-11-08 15:30:02 +01:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " allow_rmb_select " ) , " set_allow_rmb_select " , " get_allow_rmb_select " ) ;
2019-12-26 04:27:28 +01:00
ADD_PROPERTY ( PropertyInfo ( Variant : : INT , " max_text_lines " , PROPERTY_HINT_RANGE , " 1,10,1,or_greater " ) , " set_max_text_lines " , " get_max_text_lines " ) ;
2018-11-08 15:30:02 +01:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " auto_height " ) , " set_auto_height " , " has_auto_height " ) ;
2021-08-21 00:22:09 +02:00
ADD_PROPERTY ( PropertyInfo ( Variant : : INT , " text_overrun_behavior " , PROPERTY_HINT_ENUM , " Trim Nothing,Trim Characters,Trim Words,Ellipsis,Word Ellipsis " ) , " set_text_overrun_behavior " , " get_text_overrun_behavior " ) ;
2017-07-04 13:38:56 +02:00
ADD_GROUP ( " Columns " , " " ) ;
2019-12-26 04:27:28 +01:00
ADD_PROPERTY ( PropertyInfo ( Variant : : INT , " max_columns " , PROPERTY_HINT_RANGE , " 0,10,1,or_greater " ) , " set_max_columns " , " get_max_columns " ) ;
2018-11-08 15:30:02 +01:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " same_column_width " ) , " set_same_column_width " , " is_same_column_width " ) ;
2019-12-26 04:27:28 +01:00
ADD_PROPERTY ( PropertyInfo ( Variant : : INT , " fixed_column_width " , PROPERTY_HINT_RANGE , " 0,100,1,or_greater " ) , " set_fixed_column_width " , " get_fixed_column_width " ) ;
2017-07-04 13:38:56 +02:00
ADD_GROUP ( " Icon " , " " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : INT , " icon_mode " , PROPERTY_HINT_ENUM , " Top,Left " ) , " set_icon_mode " , " get_icon_mode " ) ;
Variant: Added 64-bit packed arrays, renamed Variant::REAL to FLOAT.
- Renames PackedIntArray to PackedInt32Array.
- Renames PackedFloatArray to PackedFloat32Array.
- Adds PackedInt64Array and PackedFloat64Array.
- Renames Variant::REAL to Variant::FLOAT for consistency.
Packed arrays are for storing large amount of data and creating stuff like
meshes, buffers. textures, etc. Forcing them to be 64 is a huge waste of
memory. That said, many users requested the ability to have 64 bits packed
arrays for their games, so this is just an optional added type.
For Variant, the float datatype is always 64 bits, and exposed as `float`.
We still have `real_t` which is the datatype that can change from 32 to 64
bits depending on a compile flag (not entirely working right now, but that's
the idea). It affects math related datatypes and code only.
Neither Variant nor PackedArray make use of real_t, which is only intended
for math precision, so the term is removed from there to keep only float.
2020-02-24 19:20:53 +01:00
ADD_PROPERTY ( PropertyInfo ( Variant : : FLOAT , " icon_scale " ) , " set_icon_scale " , " get_icon_scale " ) ;
2018-11-08 15:30:02 +01:00
ADD_PROPERTY ( PropertyInfo ( Variant : : VECTOR2 , " fixed_icon_size " ) , " set_fixed_icon_size " , " get_fixed_icon_size " ) ;
2017-07-04 13:38:56 +02:00
2017-08-20 17:45:01 +02:00
BIND_ENUM_CONSTANT ( ICON_MODE_TOP ) ;
BIND_ENUM_CONSTANT ( ICON_MODE_LEFT ) ;
BIND_ENUM_CONSTANT ( SELECT_SINGLE ) ;
BIND_ENUM_CONSTANT ( SELECT_MULTI ) ;
2015-06-06 14:44:38 +02:00
2017-03-05 16:44:50 +01:00
ADD_SIGNAL ( MethodInfo ( " item_selected " , PropertyInfo ( Variant : : INT , " index " ) ) ) ;
2017-09-10 15:37:49 +02:00
ADD_SIGNAL ( MethodInfo ( " item_rmb_selected " , PropertyInfo ( Variant : : INT , " index " ) , PropertyInfo ( Variant : : VECTOR2 , " at_position " ) ) ) ;
2017-03-05 16:44:50 +01:00
ADD_SIGNAL ( MethodInfo ( " multi_selected " , PropertyInfo ( Variant : : INT , " index " ) , PropertyInfo ( Variant : : BOOL , " selected " ) ) ) ;
ADD_SIGNAL ( MethodInfo ( " item_activated " , PropertyInfo ( Variant : : INT , " index " ) ) ) ;
2017-11-20 19:25:13 +01:00
ADD_SIGNAL ( MethodInfo ( " rmb_clicked " , PropertyInfo ( Variant : : VECTOR2 , " at_position " ) ) ) ;
2017-11-24 14:39:02 +01:00
ADD_SIGNAL ( MethodInfo ( " nothing_selected " ) ) ;
2015-06-06 14:44:38 +02:00
2017-03-05 16:44:50 +01:00
GLOBAL_DEF ( " gui/timers/incremental_search_max_interval_msec " , 2000 ) ;
2018-10-05 18:43:53 +02:00
ProjectSettings : : get_singleton ( ) - > set_custom_property_info ( " gui/timers/incremental_search_max_interval_msec " , PropertyInfo ( Variant : : INT , " gui/timers/incremental_search_max_interval_msec " , PROPERTY_HINT_RANGE , " 0,10000,1,or_greater " ) ) ; // No negative numbers
2015-06-06 14:44:38 +02:00
}
ItemList : : ItemList ( ) {
2017-03-05 16:44:50 +01:00
scroll_bar = memnew ( VScrollBar ) ;
2015-06-06 14:44:38 +02:00
add_child ( scroll_bar ) ;
2020-02-21 18:28:45 +01:00
scroll_bar - > connect ( " value_changed " , callable_mp ( this , & ItemList : : _scroll_changed ) ) ;
2015-06-06 14:44:38 +02:00
set_focus_mode ( FOCUS_ALL ) ;
2017-10-31 10:58:53 +01:00
set_clip_contents ( true ) ;
2015-06-06 14:44:38 +02:00
}
ItemList : : ~ ItemList ( ) {
}