2016-06-18 14:46:12 +02:00
/**************************************************************************/
/* item_list.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* 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"
2021-11-04 15:27:23 +01:00
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"
2023-09-08 21:00:10 +02:00
# include "scene/theme/theme_db.h"
2020-09-03 13:22:16 +02:00
2023-03-09 12:57:59 +01:00
void ItemList : : _shape_text ( int p_idx ) {
2020-09-03 13:22:16 +02:00
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 ) ;
}
2023-10-18 21:06:28 +02:00
item . text_buf - > add_string ( item . xl_text , theme_cache . font , theme_cache . font_size , item . language ) ;
2020-09-03 13:22:16 +02:00
if ( icon_mode = = ICON_MODE_TOP & & max_text_lines > 0 ) {
2022-08-30 10:56:17 +02:00
item . text_buf - > set_break_flags ( TextServer : : BREAK_MANDATORY | TextServer : : BREAK_WORD_BOUND | TextServer : : BREAK_GRAPHEME_BOUND | TextServer : : BREAK_TRIM_EDGE_SPACES ) ;
2020-09-03 13:22:16 +02:00
} else {
2022-07-11 11:40:31 +02:00
item . text_buf - > set_break_flags ( TextServer : : BREAK_NONE ) ;
2020-09-03 13:22:16 +02:00
}
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 ;
item . icon = p_texture ;
item . text = p_item ;
2023-10-18 21:06:28 +02:00
item . xl_text = atr ( p_item ) ;
2015-06-06 14:44:38 +02:00
item . selectable = p_selectable ;
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
2023-03-09 12:57:59 +01:00
_shape_text ( items . size ( ) - 1 ) ;
2020-09-03 13:22:16 +02:00
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
2015-06-06 14:44:38 +02:00
shape_changed = true ;
2021-10-27 18:29:44 +02:00
notify_property_list_changed ( ) ;
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 ;
item . icon = p_item ;
item . selectable = p_selectable ;
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
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
2015-06-06 14:44:38 +02:00
shape_changed = true ;
2021-10-27 18:29:44 +02:00
notify_property_list_changed ( ) ;
2019-11-17 22:45:08 +01:00
return item_id ;
2015-06-06 14:44:38 +02:00
}
void ItemList : : set_item_text ( int p_idx , const String & p_text ) {
2022-03-12 01:06:45 +01:00
if ( p_idx < 0 ) {
p_idx + = get_item_count ( ) ;
}
2015-06-06 14:44:38 +02:00
ERR_FAIL_INDEX ( p_idx , items . size ( ) ) ;
2022-03-16 08:50:48 +01:00
if ( items [ p_idx ] . text = = p_text ) {
return ;
}
2018-07-25 03:11:03 +02:00
items . write [ p_idx ] . text = p_text ;
2023-10-18 21:06:28 +02:00
items . write [ p_idx ] . xl_text = atr ( p_text ) ;
2023-03-09 12:57:59 +01:00
_shape_text ( p_idx ) ;
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
2015-06-06 14:44:38 +02:00
shape_changed = true ;
}
String ItemList : : get_item_text ( int p_idx ) const {
ERR_FAIL_INDEX_V ( p_idx , items . size ( ) , String ( ) ) ;
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 ) {
2022-03-12 01:06:45 +01:00
if ( p_idx < 0 ) {
p_idx + = get_item_count ( ) ;
}
2020-09-03 13:22:16 +02:00
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 ;
2023-03-09 12:57:59 +01:00
_shape_text ( p_idx ) ;
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
2020-09-03 13:22:16 +02:00
}
}
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 : : set_item_language ( int p_idx , const String & p_language ) {
2022-03-12 01:06:45 +01:00
if ( p_idx < 0 ) {
p_idx + = get_item_count ( ) ;
}
2020-09-03 13:22:16 +02:00
ERR_FAIL_INDEX ( p_idx , items . size ( ) ) ;
if ( items [ p_idx ] . language ! = p_language ) {
items . write [ p_idx ] . language = p_language ;
2023-03-09 12:57:59 +01:00
_shape_text ( p_idx ) ;
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
2020-09-03 13:22:16 +02:00
}
}
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 ) {
2022-03-12 01:06:45 +01:00
if ( p_idx < 0 ) {
p_idx + = get_item_count ( ) ;
}
2016-09-07 17:21:20 +02: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 {
ERR_FAIL_INDEX_V ( p_idx , items . size ( ) , false ) ;
return items [ p_idx ] . tooltip_enabled ;
}
2015-06-06 14:44:38 +02:00
void ItemList : : set_item_tooltip ( int p_idx , const String & p_tooltip ) {
2022-03-12 01:06:45 +01:00
if ( p_idx < 0 ) {
p_idx + = get_item_count ( ) ;
}
2015-06-06 14:44:38 +02:00
ERR_FAIL_INDEX ( p_idx , items . size ( ) ) ;
2022-03-16 08:50:48 +01:00
if ( items [ p_idx ] . tooltip = = p_tooltip ) {
return ;
}
2018-07-25 03:11:03 +02:00
items . write [ p_idx ] . tooltip = p_tooltip ;
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
2015-06-06 14:44:38 +02:00
shape_changed = true ;
}
String ItemList : : get_item_tooltip ( int p_idx ) const {
ERR_FAIL_INDEX_V ( p_idx , items . size ( ) , String ( ) ) ;
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 ) {
2022-03-12 01:06:45 +01:00
if ( p_idx < 0 ) {
p_idx + = get_item_count ( ) ;
}
2015-06-06 14:44:38 +02:00
ERR_FAIL_INDEX ( p_idx , items . size ( ) ) ;
2022-03-16 08:50:48 +01:00
if ( items [ p_idx ] . icon = = p_icon ) {
return ;
}
2018-07-25 03:11:03 +02:00
items . write [ p_idx ] . icon = p_icon ;
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
2015-06-06 14:44:38 +02:00
shape_changed = true ;
}
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 ) {
2022-03-12 01:06:45 +01:00
if ( p_idx < 0 ) {
p_idx + = get_item_count ( ) ;
}
2018-10-29 17:16:18 +01:00
ERR_FAIL_INDEX ( p_idx , items . size ( ) ) ;
2022-03-16 08:50:48 +01:00
if ( items [ p_idx ] . icon_transposed = = p_transposed ) {
return ;
}
2018-10-29 17:16:18 +01:00
items . write [ p_idx ] . icon_transposed = p_transposed ;
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
2018-10-29 17:16:18 +01:00
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 ;
}
2016-03-13 16:23:49 +01:00
void ItemList : : set_item_icon_region ( int p_idx , const Rect2 & p_region ) {
2022-03-12 01:06:45 +01:00
if ( p_idx < 0 ) {
p_idx + = get_item_count ( ) ;
}
2016-03-13 16:23:49 +01:00
ERR_FAIL_INDEX ( p_idx , items . size ( ) ) ;
2022-03-16 08:50:48 +01:00
if ( items [ p_idx ] . icon_region = = p_region ) {
return ;
}
2018-07-25 03:11:03 +02:00
items . write [ p_idx ] . icon_region = p_region ;
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
2016-03-13 16:23:49 +01:00
shape_changed = true ;
}
Rect2 ItemList : : get_item_icon_region ( int p_idx ) const {
ERR_FAIL_INDEX_V ( p_idx , items . size ( ) , Rect2 ( ) ) ;
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 ) {
2022-03-12 01:06:45 +01:00
if ( p_idx < 0 ) {
p_idx + = get_item_count ( ) ;
}
2018-03-11 15:59:50 +01:00
ERR_FAIL_INDEX ( p_idx , items . size ( ) ) ;
2022-03-16 08:50:48 +01:00
if ( items [ p_idx ] . icon_modulate = = p_modulate ) {
return ;
}
2018-07-25 03:11:03 +02:00
items . write [ p_idx ] . icon_modulate = p_modulate ;
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
2018-03-11 15:59:50 +01:00
}
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 ;
}
2015-06-22 05:03:19 +02:00
void ItemList : : set_item_custom_bg_color ( int p_idx , const Color & p_custom_bg_color ) {
2022-03-12 01:06:45 +01:00
if ( p_idx < 0 ) {
p_idx + = get_item_count ( ) ;
}
2015-06-22 05:03:19 +02:00
ERR_FAIL_INDEX ( p_idx , items . size ( ) ) ;
2022-03-16 08:50:48 +01:00
if ( items [ p_idx ] . custom_bg = = p_custom_bg_color ) {
return ;
}
2018-07-25 03:11:03 +02:00
items . write [ p_idx ] . custom_bg = p_custom_bg_color ;
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
2015-06-22 05:03:19 +02:00
}
Color ItemList : : get_item_custom_bg_color ( int p_idx ) const {
ERR_FAIL_INDEX_V ( p_idx , items . size ( ) , Color ( ) ) ;
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 ) {
2022-03-12 01:06:45 +01:00
if ( p_idx < 0 ) {
p_idx + = get_item_count ( ) ;
}
2017-09-03 09:44:59 +02:00
ERR_FAIL_INDEX ( p_idx , items . size ( ) ) ;
2022-03-16 08:50:48 +01:00
if ( items [ p_idx ] . custom_fg = = p_custom_fg_color ) {
return ;
}
2018-07-25 03:11:03 +02:00
items . write [ p_idx ] . custom_fg = p_custom_fg_color ;
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
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 ;
}
2023-05-08 09:57:49 +02:00
Rect2 ItemList : : get_item_rect ( int p_idx , bool p_expand ) const {
ERR_FAIL_INDEX_V ( p_idx , items . size ( ) , Rect2 ( ) ) ;
Rect2 ret = items [ p_idx ] . rect_cache ;
ret . position + = theme_cache . panel_style - > get_offset ( ) ;
if ( p_expand & & p_idx % current_columns = = current_columns - 1 ) {
ret . size . width = get_size ( ) . width - ret . position . x ;
}
return ret ;
}
2019-06-11 20:43:37 +02:00
void ItemList : : set_item_tag_icon ( int p_idx , const Ref < Texture2D > & p_tag_icon ) {
2022-03-12 01:06:45 +01:00
if ( p_idx < 0 ) {
p_idx + = get_item_count ( ) ;
}
2015-06-22 05:03:19 +02:00
ERR_FAIL_INDEX ( p_idx , items . size ( ) ) ;
2015-06-06 14:44:38 +02:00
2022-03-16 08:50:48 +01:00
if ( items [ p_idx ] . tag_icon = = p_tag_icon ) {
return ;
}
2018-07-25 03:11:03 +02:00
items . write [ p_idx ] . tag_icon = p_tag_icon ;
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
2015-06-06 14:44:38 +02:00
shape_changed = true ;
}
2020-05-14 14:29:06 +02:00
2015-06-06 14:44:38 +02:00
void ItemList : : set_item_selectable ( int p_idx , bool p_selectable ) {
2022-03-12 01:06:45 +01:00
if ( p_idx < 0 ) {
p_idx + = get_item_count ( ) ;
}
2015-06-06 14:44:38 +02:00
ERR_FAIL_INDEX ( p_idx , items . size ( ) ) ;
2018-07-25 03:11:03 +02:00
items . write [ p_idx ] . selectable = p_selectable ;
2015-06-06 14:44:38 +02:00
}
bool ItemList : : is_item_selectable ( int p_idx ) const {
ERR_FAIL_INDEX_V ( p_idx , items . size ( ) , false ) ;
return items [ p_idx ] . selectable ;
}
void ItemList : : set_item_disabled ( int p_idx , bool p_disabled ) {
2022-03-12 01:06:45 +01:00
if ( p_idx < 0 ) {
p_idx + = get_item_count ( ) ;
}
2015-06-06 14:44:38 +02:00
ERR_FAIL_INDEX ( p_idx , items . size ( ) ) ;
2022-03-16 08:50:48 +01:00
if ( items [ p_idx ] . disabled = = p_disabled ) {
return ;
}
2018-07-25 03:11:03 +02:00
items . write [ p_idx ] . disabled = p_disabled ;
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
2015-06-06 14:44:38 +02:00
}
bool ItemList : : is_item_disabled ( int p_idx ) const {
ERR_FAIL_INDEX_V ( p_idx , items . size ( ) , false ) ;
return items [ p_idx ] . disabled ;
}
void ItemList : : set_item_metadata ( int p_idx , const Variant & p_metadata ) {
2022-03-12 01:06:45 +01:00
if ( p_idx < 0 ) {
p_idx + = get_item_count ( ) ;
}
2015-06-06 14:44:38 +02:00
ERR_FAIL_INDEX ( p_idx , items . size ( ) ) ;
2022-03-16 08:50:48 +01:00
if ( items [ p_idx ] . metadata = = p_metadata ) {
return ;
}
2018-07-25 03:11:03 +02:00
items . write [ p_idx ] . metadata = p_metadata ;
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
2015-06-06 14:44:38 +02:00
shape_changed = true ;
}
Variant ItemList : : get_item_metadata ( int p_idx ) const {
ERR_FAIL_INDEX_V ( p_idx , items . size ( ) , Variant ( ) ) ;
return items [ p_idx ] . metadata ;
}
2020-05-14 14:29:06 +02:00
2015-06-06 14:44:38 +02:00
void ItemList : : select ( int p_idx , bool p_single ) {
ERR_FAIL_INDEX ( p_idx , items . size ( ) ) ;
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 ;
}
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
}
current = p_idx ;
2015-08-24 01:15:56 +02:00
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
}
}
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
2015-06-06 14:44:38 +02:00
}
2020-05-14 14:29:06 +02:00
2020-12-21 11:26:41 +01:00
void ItemList : : deselect ( int p_idx ) {
2015-06-06 14:44:38 +02:00
ERR_FAIL_INDEX ( p_idx , items . size ( ) ) ;
if ( select_mode ! = SELECT_MULTI ) {
2018-07-25 03:11:03 +02:00
items . write [ p_idx ] . selected = false ;
2015-06-06 14:44:38 +02:00
current = - 1 ;
} else {
2018-07-25 03:11:03 +02:00
items . write [ p_idx ] . selected = false ;
2015-06-06 14:44:38 +02:00
}
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
2015-06-06 14:44:38 +02:00
}
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 ;
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
2017-11-24 14:39:02 +01:00
}
2015-06-06 14:44:38 +02:00
bool ItemList : : is_selected ( int p_idx ) const {
ERR_FAIL_INDEX_V ( p_idx , items . size ( ) , false ) ;
return items [ p_idx ] . selected ;
}
void ItemList : : set_current ( int p_current ) {
ERR_FAIL_INDEX ( p_current , items . size ( ) ) ;
2022-03-16 08:50:48 +01:00
if ( current = = p_current ) {
return ;
}
2020-05-14 16:41:43 +02:00
if ( select_mode = = SELECT_SINGLE ) {
2015-06-06 14:44:38 +02:00
select ( p_current , true ) ;
2020-05-14 16:41:43 +02:00
} else {
2015-06-06 14:44:38 +02:00
current = p_current ;
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
2015-06-06 14:44:38 +02:00
}
}
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 ] ;
2021-07-04 00:17:03 +02:00
items . remove_at ( p_from_idx ) ;
2018-03-13 15:19:04 +01:00
items . insert ( p_to_idx , item ) ;
2015-11-17 13:46:08 +01:00
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
2018-03-13 15:19:04 +01:00
shape_changed = true ;
2021-10-27 18:29:44 +02:00
notify_property_list_changed ( ) ;
}
void ItemList : : set_item_count ( int p_count ) {
ERR_FAIL_COND ( p_count < 0 ) ;
2022-03-16 08:50:48 +01:00
if ( items . size ( ) = = p_count ) {
return ;
}
2021-10-27 18:29:44 +02:00
items . resize ( p_count ) ;
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
2021-10-27 18:29:44 +02:00
shape_changed = true ;
notify_property_list_changed ( ) ;
2015-11-17 13:46:08 +01:00
}
2015-06-06 14:44:38 +02:00
int ItemList : : get_item_count ( ) const {
return items . size ( ) ;
}
2020-05-14 14:29:06 +02:00
2015-06-06 14:44:38 +02:00
void ItemList : : remove_item ( int p_idx ) {
ERR_FAIL_INDEX ( p_idx , items . size ( ) ) ;
2021-07-04 00:17:03 +02:00
items . remove_at ( p_idx ) ;
2021-05-07 15:41:39 +02:00
if ( current = = p_idx ) {
current = - 1 ;
}
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
2015-06-06 14:44:38 +02:00
shape_changed = true ;
2016-05-04 22:41:58 +02:00
defer_select_single = - 1 ;
2021-10-27 18:29:44 +02:00
notify_property_list_changed ( ) ;
2015-06-06 14:44:38 +02:00
}
void ItemList : : clear ( ) {
items . clear ( ) ;
current = - 1 ;
2015-08-24 01:15:56 +02:00
ensure_selected_visible = false ;
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
2016-07-22 16:38:16 +02:00
shape_changed = true ;
2016-05-04 22:41:58 +02:00
defer_select_single = - 1 ;
2021-10-27 18:29:44 +02:00
notify_property_list_changed ( ) ;
2015-06-06 14:44:38 +02:00
}
void ItemList : : set_fixed_column_width ( int p_size ) {
ERR_FAIL_COND ( p_size < 0 ) ;
2022-03-16 08:50:48 +01:00
if ( fixed_column_width = = p_size ) {
return ;
}
2015-06-06 14:44:38 +02:00
fixed_column_width = p_size ;
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
2015-06-06 14:44:38 +02:00
shape_changed = true ;
}
2020-05-14 14:29:06 +02:00
2015-06-06 14:44:38 +02:00
int ItemList : : get_fixed_column_width ( ) const {
return fixed_column_width ;
}
2016-05-27 21:42:51 +02:00
void ItemList : : set_same_column_width ( bool p_enable ) {
2022-03-16 08:50:48 +01:00
if ( same_column_width = = p_enable ) {
return ;
}
2016-05-27 21:42:51 +02:00
same_column_width = p_enable ;
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
2016-05-27 21:42:51 +02:00
shape_changed = true ;
}
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 ;
}
2015-06-06 14:44:38 +02: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 ) {
2022-08-30 10:56:17 +02:00
items . write [ i ] . text_buf - > set_break_flags ( TextServer : : BREAK_MANDATORY | TextServer : : BREAK_WORD_BOUND | TextServer : : BREAK_GRAPHEME_BOUND | TextServer : : BREAK_TRIM_EDGE_SPACES ) ;
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 {
2022-07-11 11:40:31 +02:00
items . write [ i ] . text_buf - > set_break_flags ( TextServer : : BREAK_NONE ) ;
2020-09-03 13:22:16 +02:00
}
}
shape_changed = true ;
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
2020-09-03 13:22:16 +02:00
}
2015-06-06 14:44:38 +02:00
}
2020-05-14 14:29:06 +02:00
2015-06-06 14:44:38 +02:00
int ItemList : : get_max_text_lines ( ) const {
return max_text_lines ;
}
void ItemList : : set_max_columns ( int p_amount ) {
ERR_FAIL_COND ( p_amount < 0 ) ;
2022-03-16 08:50:48 +01:00
if ( max_columns = = p_amount ) {
return ;
}
2015-06-06 14:44:38 +02:00
max_columns = p_amount ;
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
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
2015-06-06 14:44:38 +02:00
int ItemList : : get_max_columns ( ) const {
return max_columns ;
}
void ItemList : : set_select_mode ( SelectMode p_mode ) {
2022-03-16 08:50:48 +01:00
if ( select_mode = = p_mode ) {
return ;
}
2015-06-06 14:44:38 +02:00
select_mode = p_mode ;
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
2015-06-06 14:44:38 +02:00
}
ItemList : : SelectMode ItemList : : get_select_mode ( ) const {
return select_mode ;
}
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 ) {
2022-08-30 10:56:17 +02:00
items . write [ i ] . text_buf - > set_break_flags ( TextServer : : BREAK_MANDATORY | TextServer : : BREAK_WORD_BOUND | TextServer : : BREAK_GRAPHEME_BOUND | TextServer : : BREAK_TRIM_EDGE_SPACES ) ;
2020-09-03 13:22:16 +02:00
} else {
2022-07-11 11:40:31 +02:00
items . write [ i ] . text_buf - > set_break_flags ( TextServer : : BREAK_NONE ) ;
2020-09-03 13:22:16 +02:00
}
}
shape_changed = true ;
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
2020-09-03 13:22:16 +02:00
}
2015-06-06 14:44:38 +02:00
}
2018-10-29 17:16:18 +01:00
2015-06-06 14:44:38 +02:00
ItemList : : IconMode ItemList : : get_icon_mode ( ) const {
return icon_mode ;
}
2022-08-13 19:22:07 +02:00
void ItemList : : set_fixed_icon_size ( const Size2i & p_size ) {
2022-03-16 08:50:48 +01:00
if ( fixed_icon_size = = p_size ) {
return ;
}
2016-06-12 21:51:27 +02:00
fixed_icon_size = p_size ;
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
2023-05-08 10:25:08 +02:00
shape_changed = true ;
2016-05-15 04:48:23 +02:00
}
2022-08-13 19:22:07 +02:00
Size2i ItemList : : get_fixed_icon_size ( ) const {
2016-06-12 21:51:27 +02:00
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
2024-06-02 03:15:16 +02:00
void ItemList : : set_fixed_tag_icon_size ( const Size2i & p_size ) {
if ( fixed_tag_icon_size = = p_size ) {
return ;
}
fixed_tag_icon_size = p_size ;
queue_redraw ( ) ;
shape_changed = true ;
}
2021-08-22 17:37:22 +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 ( ) ) ;
2020-03-25 01:58:04 +01:00
# define CAN_SELECT(i) (items[i].selectable && !items[i].disabled)
# define IS_SAME_ROW(i, row) (i / current_columns == row)
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 ( ) ) {
2016-05-04 22:41:58 +02:00
defer_select_single = - 1 ;
return ;
}
2016-05-16 01:25:51 +02:00
2017-05-20 17:38:03 +02:00
Ref < InputEventMouseButton > mb = p_event ;
2021-08-13 23:31:57 +02:00
if ( defer_select_single > = 0 & & mb . is_valid ( ) & & mb - > get_button_index ( ) = = MouseButton : : LEFT & & ! mb - > is_pressed ( ) ) {
2016-05-04 22:41:58 +02: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 ) ;
2016-05-04 22:41:58 +02:00
defer_select_single = - 1 ;
return ;
}
2023-03-10 19:28:35 +01:00
if ( mm . is_valid ( ) ) {
int closest = get_item_at_position ( mm - > get_position ( ) , true ) ;
if ( closest ! = hovered ) {
hovered = closest ;
queue_redraw ( ) ;
}
}
2021-11-26 00:53:27 +01:00
if ( mb . is_valid ( ) & & mb - > is_pressed ( ) ) {
2015-06-06 14:44:38 +02:00
search_string = " " ; //any mousepress cancels
2020-09-03 13:22:16 +02:00
2022-09-21 15:37:01 +02:00
int closest = get_item_at_position ( mb - > get_position ( ) , true ) ;
2015-06-06 14:44:38 +02:00
2021-11-26 00:53:27 +01:00
if ( closest ! = - 1 & & ( mb - > get_button_index ( ) = = MouseButton : : LEFT | | ( allow_rmb_select & & mb - > get_button_index ( ) = = MouseButton : : RIGHT ) ) ) {
2015-06-06 14:44:38 +02:00
int i = closest ;
2023-03-02 20:43:11 +01:00
if ( items [ i ] . disabled ) {
// Don't emit any signal or do any action with clicked item when disabled.
return ;
}
2022-09-02 11:37:48 +02:00
if ( select_mode = = SELECT_MULTI & & items [ i ] . selected & & mb - > is_command_or_control_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 ) {
2023-03-02 20:43:11 +01:00
// Range selection.
2015-06-06 14:44:38 +02:00
int from = current ;
int to = i ;
if ( i < current ) {
SWAP ( from , to ) ;
}
for ( int j = from ; j < = to ; j + + ) {
2020-03-25 01:58:04 +01:00
if ( ! CAN_SELECT ( j ) ) {
2023-03-02 20:43:11 +01:00
// Item is not selectable during a range selection, so skip it.
2020-03-25 01:58:04 +01:00
continue ;
}
2015-06-06 14:44:38 +02:00
bool selected = ! items [ j ] . selected ;
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
}
2021-11-26 00:53:27 +01:00
emit_signal ( SNAME ( " item_clicked " ) , i , get_local_mouse_position ( ) , mb - > get_button_index ( ) ) ;
2016-05-16 01:25:51 +02:00
2015-06-06 14:44:38 +02:00
} else {
2023-03-02 20:43:11 +01:00
if ( ! mb - > is_double_click ( ) & &
! mb - > is_command_or_control_pressed ( ) & &
select_mode = = SELECT_MULTI & &
items [ i ] . selectable & &
items [ i ] . selected & &
mb - > get_button_index ( ) = = MouseButton : : LEFT ) {
2016-05-04 22:41:58 +02:00
defer_select_single = i ;
return ;
}
2023-03-02 20:43:11 +01:00
if ( items [ i ] . selectable & & ( ! items [ i ] . selected | | allow_reselect ) ) {
2022-09-02 11:37:48 +02:00
select ( i , select_mode = = SELECT_SINGLE | | ! mb - > is_command_or_control_pressed ( ) ) ;
2016-05-16 01:25:51 +02:00
2021-11-26 00:53:27 +01:00
if ( select_mode = = SELECT_SINGLE ) {
2024-05-14 14:21:31 +02:00
emit_signal ( SceneStringName ( item_selected ) , i ) ;
2021-11-26 00:53:27 +01:00
} else {
emit_signal ( SNAME ( " multi_selected " ) , i , true ) ;
2016-05-16 01:25:51 +02:00
}
2021-11-26 00:53:27 +01:00
}
2016-05-16 01:25:51 +02:00
2021-11-26 00:53:27 +01:00
emit_signal ( SNAME ( " item_clicked " ) , i , get_local_mouse_position ( ) , mb - > get_button_index ( ) ) ;
if ( mb - > get_button_index ( ) = = MouseButton : : LEFT & & mb - > is_double_click ( ) ) {
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-11-26 00:53:27 +01:00
} else if ( closest ! = - 1 ) {
2023-03-02 20:43:11 +01:00
if ( ! items [ closest ] . disabled ) {
emit_signal ( SNAME ( " item_clicked " ) , closest , get_local_mouse_position ( ) , mb - > get_button_index ( ) ) ;
}
2021-11-26 00:53:27 +01:00
} else {
// Since closest is null, more likely we clicked on empty space, so send signal to interested controls. Allows, for example, implement items deselecting.
emit_signal ( SNAME ( " empty_clicked " ) , get_local_mouse_position ( ) , mb - > get_button_index ( ) ) ;
2017-11-20 19:25:13 +01:00
}
2015-06-06 14:44:38 +02:00
}
2021-08-13 23:31:57 +02:00
if ( mb . is_valid ( ) & & mb - > get_button_index ( ) = = MouseButton : : 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-08-13 23:31:57 +02:00
if ( mb . is_valid ( ) & & mb - > get_button_index ( ) = = MouseButton : : 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 ) {
2022-09-24 10:01:02 +02:00
if ( p_event - > is_action ( " ui_up " , true ) ) {
2021-12-09 10:42:46 +01:00
if ( ! search_string . is_empty ( ) ) {
2015-06-06 14:44:38 +02:00
uint64_t now = OS : : get_singleton ( ) - > get_ticks_msec ( ) ;
uint64_t diff = now - search_time_msec ;
2022-10-18 16:43:37 +02:00
if ( diff < uint64_t ( GLOBAL_GET ( " gui/timers/incremental_search_max_interval_msec " ) ) * 2 ) {
2015-06-06 14:44:38 +02:00
for ( int i = current - 1 ; i > = 0 ; i - - ) {
2020-03-25 01:58:04 +01:00
if ( CAN_SELECT ( i ) & & items [ i ] . text . begins_with ( search_string ) ) {
2015-06-06 14:44:38 +02:00
set_current ( i ) ;
ensure_current_is_visible ( ) ;
if ( select_mode = = SELECT_SINGLE ) {
2024-05-14 14:21:31 +02:00
emit_signal ( SceneStringName ( item_selected ) , current ) ;
2015-06-06 14:44:38 +02:00
}
break ;
}
}
accept_event ( ) ;
return ;
}
}
if ( current > = current_columns ) {
2020-03-25 01:58:04 +01:00
int next = current - current_columns ;
while ( next > = 0 & & ! CAN_SELECT ( next ) ) {
next = next - current_columns ;
}
if ( next < 0 ) {
accept_event ( ) ;
return ;
}
set_current ( next ) ;
2015-06-06 14:44:38 +02:00
ensure_current_is_visible ( ) ;
if ( select_mode = = SELECT_SINGLE ) {
2024-05-14 14:21:31 +02:00
emit_signal ( SceneStringName ( item_selected ) , current ) ;
2015-06-06 14:44:38 +02:00
}
accept_event ( ) ;
}
2022-09-24 10:01:02 +02:00
} else if ( p_event - > is_action ( " ui_down " , true ) ) {
2021-12-09 10:42:46 +01:00
if ( ! search_string . is_empty ( ) ) {
2015-06-06 14:44:38 +02:00
uint64_t now = OS : : get_singleton ( ) - > get_ticks_msec ( ) ;
uint64_t diff = now - search_time_msec ;
2022-10-18 16:43:37 +02:00
if ( diff < uint64_t ( GLOBAL_GET ( " gui/timers/incremental_search_max_interval_msec " ) ) * 2 ) {
2015-06-06 14:44:38 +02:00
for ( int i = current + 1 ; i < items . size ( ) ; i + + ) {
2020-03-25 01:58:04 +01:00
if ( CAN_SELECT ( i ) & & items [ i ] . text . begins_with ( search_string ) ) {
2015-06-06 14:44:38 +02:00
set_current ( i ) ;
ensure_current_is_visible ( ) ;
if ( select_mode = = SELECT_SINGLE ) {
2024-05-14 14:21:31 +02:00
emit_signal ( SceneStringName ( item_selected ) , current ) ;
2015-06-06 14:44:38 +02:00
}
break ;
}
}
accept_event ( ) ;
return ;
}
}
if ( current < items . size ( ) - current_columns ) {
2020-03-25 01:58:04 +01:00
int next = current + current_columns ;
while ( next < items . size ( ) & & ! CAN_SELECT ( next ) ) {
next = next + current_columns ;
}
if ( next > = items . size ( ) ) {
accept_event ( ) ;
return ;
}
set_current ( next ) ;
2015-06-06 14:44:38 +02:00
ensure_current_is_visible ( ) ;
if ( select_mode = = SELECT_SINGLE ) {
2024-05-14 14:21:31 +02:00
emit_signal ( SceneStringName ( item_selected ) , current ) ;
2015-06-06 14:44:38 +02:00
}
accept_event ( ) ;
}
2022-09-24 10:01:02 +02:00
} else if ( p_event - > is_action ( " ui_page_up " , true ) ) {
2015-06-06 14:44:38 +02:00
search_string = " " ; //any mousepress cancels
for ( int i = 4 ; i > 0 ; i - - ) {
2023-01-27 18:34:18 +01:00
int index = current - current_columns * i ;
if ( index > = 0 & & index < items . size ( ) & & CAN_SELECT ( index ) ) {
set_current ( index ) ;
2015-06-06 14:44:38 +02:00
ensure_current_is_visible ( ) ;
if ( select_mode = = SELECT_SINGLE ) {
2024-05-14 14:21:31 +02:00
emit_signal ( SceneStringName ( item_selected ) , current ) ;
2015-06-06 14:44:38 +02:00
}
accept_event ( ) ;
break ;
}
}
2022-09-24 10:01:02 +02:00
} else if ( p_event - > is_action ( " ui_page_down " , true ) ) {
2015-06-06 14:44:38 +02:00
search_string = " " ; //any mousepress cancels
for ( int i = 4 ; i > 0 ; i - - ) {
2023-01-27 18:34:18 +01:00
int index = current + current_columns * i ;
if ( index > = 0 & & index < items . size ( ) & & CAN_SELECT ( index ) ) {
set_current ( index ) ;
2015-06-06 14:44:38 +02:00
ensure_current_is_visible ( ) ;
if ( select_mode = = SELECT_SINGLE ) {
2024-05-14 14:21:31 +02:00
emit_signal ( SceneStringName ( item_selected ) , current ) ;
2015-06-06 14:44:38 +02:00
}
accept_event ( ) ;
break ;
}
}
2022-09-24 10:01:02 +02:00
} else if ( p_event - > is_action ( " ui_left " , true ) ) {
2015-06-06 14:44:38 +02:00
search_string = " " ; //any mousepress cancels
if ( current % current_columns ! = 0 ) {
2020-03-25 01:58:04 +01:00
int current_row = current / current_columns ;
int next = current - 1 ;
2023-01-27 18:34:18 +01:00
while ( next > = 0 & & ! CAN_SELECT ( next ) ) {
2020-03-25 01:58:04 +01:00
next = next - 1 ;
}
if ( next < 0 | | ! IS_SAME_ROW ( next , current_row ) ) {
accept_event ( ) ;
return ;
}
set_current ( next ) ;
2015-06-06 14:44:38 +02:00
ensure_current_is_visible ( ) ;
if ( select_mode = = SELECT_SINGLE ) {
2024-05-14 14:21:31 +02:00
emit_signal ( SceneStringName ( item_selected ) , current ) ;
2015-06-06 14:44:38 +02:00
}
accept_event ( ) ;
}
2022-09-24 10:01:02 +02:00
} else if ( p_event - > is_action ( " ui_right " , true ) ) {
2015-06-06 14:44:38 +02:00
search_string = " " ; //any mousepress cancels
2018-04-14 14:36:53 +02:00
if ( current % current_columns ! = ( current_columns - 1 ) & & current + 1 < items . size ( ) ) {
2020-03-25 01:58:04 +01:00
int current_row = current / current_columns ;
int next = current + 1 ;
2023-01-27 18:34:18 +01:00
while ( next < items . size ( ) & & ! CAN_SELECT ( next ) ) {
2020-03-25 01:58:04 +01:00
next = next + 1 ;
}
if ( items . size ( ) < = next | | ! IS_SAME_ROW ( next , current_row ) ) {
accept_event ( ) ;
return ;
}
set_current ( next ) ;
2015-06-06 14:44:38 +02:00
ensure_current_is_visible ( ) ;
if ( select_mode = = SELECT_SINGLE ) {
2024-05-14 14:21:31 +02:00
emit_signal ( SceneStringName ( item_selected ) , current ) ;
2015-06-06 14:44:38 +02:00
}
accept_event ( ) ;
}
2022-09-24 10:01:02 +02:00
} else if ( p_event - > is_action ( " ui_cancel " , true ) ) {
2015-06-06 14:44:38 +02:00
search_string = " " ;
2022-09-24 10:01:02 +02:00
} else if ( p_event - > is_action ( " ui_select " , true ) & & select_mode = = SELECT_MULTI ) {
2019-01-17 15:54:24 +01:00
if ( current > = 0 & & current < items . size ( ) ) {
2023-03-02 20:43:11 +01:00
if ( CAN_SELECT ( current ) & & ! items [ current ] . selected ) {
2015-06-06 14:44:38 +02: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
}
}
2022-09-24 10:01:02 +02:00
} else if ( p_event - > is_action ( " ui_accept " , true ) ) {
2021-03-12 14:35:16 +01:00
search_string = " " ; //any mousepress cancels
2015-06-06 14:44:38 +02:00
2023-03-02 20:43:11 +01:00
if ( current > = 0 & & current < items . size ( ) & & ! items [ current ] . disabled ) {
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
2023-04-18 08:50:24 +02:00
if ( allow_search & & k . is_valid ( ) & & k - > get_unicode ( ) ) {
2015-06-06 14:44:38 +02:00
uint64_t now = OS : : get_singleton ( ) - > get_ticks_msec ( ) ;
uint64_t diff = now - search_time_msec ;
2022-10-20 15:43:17 +02:00
uint64_t max_interval = uint64_t ( GLOBAL_GET ( " gui/timers/incremental_search_max_interval_msec " ) ) ;
2015-06-06 14:44:38 +02:00
search_time_msec = now ;
if ( diff > max_interval ) {
search_string = " " ;
}
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 ( ) ;
if ( select_mode = = SELECT_SINGLE ) {
2024-05-14 14:21:31 +02:00
emit_signal ( SceneStringName ( 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
}
2020-03-25 01:58:04 +01:00
# undef CAN_SELECT
# undef IS_SAME_ROW
2015-06-06 14:44:38 +02:00
}
void ItemList : : ensure_current_is_visible ( ) {
2015-08-24 01:15:56 +02:00
ensure_selected_visible = true ;
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
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 ) {
Size2 size = p_max_size ;
int tex_width = p_size . width * size . height / p_size . height ;
int tex_height = size . height ;
2016-05-15 04:48:23 +02:00
2016-06-12 21:51:27 +02:00
if ( tex_width > size . width ) {
tex_width = size . width ;
2016-06-12 22:10:34 +02:00
tex_height = p_size . height * tex_width / p_size . width ;
2016-05-15 04:48:23 +02:00
}
2016-06-12 21:51:27 +02: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
2016-06-12 21:51:27 +02: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 ) {
2022-02-15 18:06:48 +01:00
switch ( p_what ) {
case NOTIFICATION_RESIZED : {
shape_changed = true ;
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
2022-02-15 18:06:48 +01:00
} break ;
case NOTIFICATION_LAYOUT_DIRECTION_CHANGED :
case NOTIFICATION_THEME_CHANGED : {
for ( int i = 0 ; i < items . size ( ) ; i + + ) {
2023-03-09 12:57:59 +01:00
_shape_text ( i ) ;
2022-02-15 18:06:48 +01:00
}
shape_changed = true ;
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
2022-02-15 18:06:48 +01:00
} break ;
2023-10-18 21:06:28 +02:00
case NOTIFICATION_TRANSLATION_CHANGED : {
for ( int i = 0 ; i < items . size ( ) ; i + + ) {
items . write [ i ] . xl_text = atr ( items [ i ] . text ) ;
_shape_text ( i ) ;
}
shape_changed = true ;
queue_redraw ( ) ;
} break ;
2015-06-06 14:44:38 +02:00
2022-02-15 18:06:48 +01:00
case NOTIFICATION_DRAW : {
2022-07-29 18:49:14 +02:00
force_update_list_size ( ) ;
2023-03-09 12:57:59 +01:00
int scroll_bar_minwidth = scroll_bar - > get_minimum_size ( ) . x ;
scroll_bar - > set_anchor_and_offset ( SIDE_LEFT , ANCHOR_END , - scroll_bar_minwidth ) ;
2022-02-15 18:06:48 +01:00
scroll_bar - > set_anchor_and_offset ( SIDE_RIGHT , ANCHOR_END , 0 ) ;
2022-09-06 19:09:32 +02:00
scroll_bar - > set_anchor_and_offset ( SIDE_TOP , ANCHOR_BEGIN , theme_cache . panel_style - > get_margin ( SIDE_TOP ) ) ;
scroll_bar - > set_anchor_and_offset ( SIDE_BOTTOM , ANCHOR_END , - theme_cache . panel_style - > get_margin ( SIDE_BOTTOM ) ) ;
2015-06-06 14:44:38 +02:00
2022-02-15 18:06:48 +01:00
Size2 size = get_size ( ) ;
2022-09-06 19:09:32 +02:00
int width = size . width - theme_cache . panel_style - > get_minimum_size ( ) . width ;
2023-03-09 12:57:59 +01:00
if ( scroll_bar - > is_visible ( ) ) {
width - = scroll_bar_minwidth ;
}
2015-06-06 14:44:38 +02:00
2022-09-06 19:09:32 +02:00
draw_style_box ( theme_cache . panel_style , Rect2 ( Point2 ( ) , size ) ) ;
2015-06-06 14:44:38 +02:00
2022-08-31 14:02:40 +02:00
Ref < StyleBox > sbsel ;
Ref < StyleBox > cursor ;
2015-06-06 14:44:38 +02:00
2022-08-31 14:02:40 +02:00
if ( has_focus ( ) ) {
sbsel = theme_cache . selected_focus_style ;
cursor = theme_cache . cursor_focus_style ;
} else {
sbsel = theme_cache . selected_style ;
cursor = theme_cache . cursor_style ;
}
2022-02-15 18:06:48 +01:00
bool rtl = is_layout_rtl ( ) ;
2015-06-06 14:44:38 +02:00
2022-02-15 18:06:48 +01:00
if ( has_focus ( ) ) {
RenderingServer : : get_singleton ( ) - > canvas_item_add_clip_ignore ( get_canvas_item ( ) , true ) ;
2022-09-06 19:09:32 +02:00
draw_style_box ( theme_cache . focus_style , Rect2 ( Point2 ( ) , size ) ) ;
2022-02-15 18:06:48 +01:00
RenderingServer : : get_singleton ( ) - > canvas_item_add_clip_ignore ( get_canvas_item ( ) , false ) ;
}
2015-06-06 14:44:38 +02:00
2023-03-09 12:57:59 +01:00
// Ensure_selected_visible needs to be checked before we draw the list.
2022-02-15 18:06:48 +01:00
if ( ensure_selected_visible & & current > = 0 & & current < items . size ( ) ) {
Rect2 r = items [ current ] . rect_cache ;
int from = scroll_bar - > get_value ( ) ;
int to = from + scroll_bar - > get_page ( ) ;
2015-06-06 14:44:38 +02:00
2022-02-15 18:06:48 +01: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 ) ) ;
2018-01-03 21:11:50 +01:00
}
}
2015-06-06 14:44:38 +02:00
2022-02-15 18:06:48 +01:00
ensure_selected_visible = false ;
2015-06-06 14:44:38 +02:00
2022-09-06 19:09:32 +02:00
Vector2 base_ofs = theme_cache . panel_style - > get_offset ( ) ;
2022-02-15 18:06:48 +01:00
base_ofs . y - = int ( scroll_bar - > get_value ( ) ) ;
2018-01-03 21:11:50 +01:00
2023-03-09 12:57:59 +01:00
// Define a visible frame to check against and optimize drawing.
const Rect2 clip ( - base_ofs , size ) ;
2015-06-06 14:44:38 +02:00
2023-08-30 10:32:58 +02:00
// Do a binary search to find the first separator that is below clip_position.y.
int first_visible_separator = 0 ;
{
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 ;
}
2023-09-24 13:06:11 +02:00
// If not in thumbnails mode, draw visible separators.
if ( icon_mode ! = ICON_MODE_TOP ) {
for ( int i = first_visible_separator ; i < separators . size ( ) ; i + + ) {
if ( separators [ i ] > clip . position . y + clip . size . y ) {
break ; // done
}
2023-08-30 10:32:58 +02:00
2023-09-24 13:06:11 +02:00
const int y = base_ofs . y + separators [ i ] ;
draw_line ( Vector2 ( theme_cache . panel_style - > get_margin ( SIDE_LEFT ) , y ) , Vector2 ( width , y ) , theme_cache . guide_color ) ;
}
2023-08-30 10:32:58 +02:00
}
2023-03-09 12:57:59 +01:00
// Do a binary search to find the first item whose rect reaches below clip.position.y.
2022-02-15 18:06:48 +01:00
int first_item_visible ;
{
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 ;
}
}
2023-03-09 12:57:59 +01:00
// We might end up with an item in columns 2, 3, etc, but we need the one from the first column.
// We can also end up in a state where lo reached hi, and so no items can be rendered; we skip that.
while ( lo < hi & & lo > 0 & & items [ lo ] . column > 0 ) {
2022-02-15 18:06:48 +01:00
lo - = 1 ;
}
2023-03-09 12:57:59 +01:00
2022-02-15 18:06:48 +01:00
first_item_visible = lo ;
2015-06-06 14:44:38 +02:00
}
2023-03-09 12:57:59 +01:00
// Draw visible items.
2022-02-15 18:06:48 +01:00
for ( int i = first_item_visible ; i < items . size ( ) ; i + + ) {
Rect2 rcache = items [ i ] . rect_cache ;
2017-06-05 02:58:29 +02:00
2022-02-15 18:06:48 +01:00
if ( rcache . position . y > clip . position . y + clip . size . y ) {
break ; // done
2020-09-03 13:22:16 +02:00
}
2022-02-15 18:06:48 +01:00
if ( ! clip . intersects ( rcache ) ) {
continue ;
2020-09-03 13:22:16 +02:00
}
2022-02-15 18:06:48 +01:00
if ( current_columns = = 1 ) {
rcache . size . width = width - rcache . position . x ;
2015-06-06 14:44:38 +02:00
}
2023-03-10 19:28:35 +01:00
bool should_draw_selected_bg = items [ i ] . selected ;
bool should_draw_hovered_bg = hovered = = i & & ! items [ i ] . selected ;
bool should_draw_custom_bg = items [ i ] . custom_bg . a > 0.001 ;
2016-03-13 16:23:49 +01:00
2023-03-10 19:28:35 +01:00
if ( should_draw_selected_bg | | should_draw_hovered_bg | | should_draw_custom_bg ) {
2022-02-15 18:06:48 +01:00
Rect2 r = rcache ;
r . position + = base_ofs ;
2016-06-12 21:51:27 +02:00
2022-02-15 18:06:48 +01:00
if ( rtl ) {
r . position . x = size . width - r . position . x - r . size . x ;
}
2016-03-13 16:23:49 +01:00
2023-03-10 19:28:35 +01:00
if ( should_draw_selected_bg ) {
draw_style_box ( sbsel , r ) ;
}
if ( should_draw_hovered_bg ) {
draw_style_box ( theme_cache . hovered_style , r ) ;
}
if ( should_draw_custom_bg ) {
draw_rect ( r , items [ i ] . custom_bg ) ;
}
2020-05-14 16:41:43 +02:00
}
2016-07-21 23:24:56 +02:00
2022-02-15 18:06:48 +01:00
Vector2 text_ofs ;
if ( items [ i ] . icon . is_valid ( ) ) {
Size2 icon_size ;
//= _adjust_to_max_size(items[i].get_icon_size(),fixed_icon_size) * icon_scale;
2018-10-29 17:16:18 +01:00
2022-02-15 18:06:48 +01:00
if ( fixed_icon_size . x > 0 & & fixed_icon_size . y > 0 ) {
icon_size = fixed_icon_size * icon_scale ;
} else {
icon_size = items [ i ] . get_icon_size ( ) * icon_scale ;
}
2020-09-03 13:22:16 +02:00
2022-02-15 18:06:48 +01:00
Vector2 icon_ofs ;
2015-06-06 14:44:38 +02:00
2022-02-15 18:06:48 +01:00
Point2 pos = items [ i ] . rect_cache . position + icon_ofs + base_ofs ;
2015-06-06 14:44:38 +02:00
2024-02-14 23:45:49 +01:00
if ( icon_mode = = ICON_MODE_TOP ) {
pos . y + = theme_cache . v_separation / 2 ;
} else {
pos . x + = theme_cache . h_separation / 2 ;
}
2022-02-15 18:06:48 +01:00
if ( icon_mode = = ICON_MODE_TOP ) {
pos . x + = Math : : floor ( ( items [ i ] . rect_cache . size . width - icon_size . width ) / 2 ) ;
2022-08-31 14:02:40 +02:00
pos . y + = theme_cache . icon_margin ;
text_ofs . y = icon_size . height + theme_cache . icon_margin * 2 ;
2022-02-15 18:06:48 +01:00
} else {
pos . y + = Math : : floor ( ( items [ i ] . rect_cache . size . height - icon_size . height ) / 2 ) ;
2022-08-31 14:02:40 +02:00
text_ofs . x = icon_size . width + theme_cache . icon_margin ;
2022-02-15 18:06:48 +01:00
}
2015-06-06 14:44:38 +02:00
2022-02-15 18:06:48 +01:00
Rect2 draw_rect = Rect2 ( pos , icon_size ) ;
2015-06-06 14:44:38 +02:00
2022-02-15 18:06:48 +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 ) ;
draw_rect . position + = adj . position ;
draw_rect . size = adj . size ;
}
2016-07-21 23:24:56 +02:00
2022-09-29 11:53:28 +02:00
Color icon_modulate = items [ i ] . icon_modulate ;
2022-02-15 18:06:48 +01:00
if ( items [ i ] . disabled ) {
2022-09-29 11:53:28 +02:00
icon_modulate . a * = 0.5 ;
2022-02-15 18:06:48 +01:00
}
2015-06-06 14:44:38 +02:00
2022-02-15 18:06:48 +01:00
// If the icon is transposed, we have to switch the size so that it is drawn correctly
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 ;
2015-06-06 14:44:38 +02:00
}
2022-02-15 18:06:48 +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
2022-02-15 18:06:48 +01:00
if ( rtl ) {
draw_rect . position . x = size . width - draw_rect . position . x - draw_rect . size . x ;
2020-12-25 22:45:28 +01:00
}
2022-09-29 11:53:28 +02:00
draw_texture_rect_region ( items [ i ] . icon , draw_rect , region , icon_modulate , items [ i ] . icon_transposed ) ;
2022-02-15 18:06:48 +01:00
}
2020-12-25 22:45:28 +01:00
2022-02-15 18:06:48 +01:00
if ( items [ i ] . tag_icon . is_valid ( ) ) {
2024-06-02 03:15:16 +02:00
Size2 tag_icon_size ;
if ( fixed_tag_icon_size . x > 0 & & fixed_tag_icon_size . y > 0 ) {
tag_icon_size = fixed_tag_icon_size ;
} else {
tag_icon_size = items [ i ] . tag_icon - > get_size ( ) ;
}
2022-02-15 18:06:48 +01:00
Point2 draw_pos = items [ i ] . rect_cache . position ;
2024-02-14 23:45:49 +01:00
draw_pos . x + = theme_cache . h_separation / 2 ;
draw_pos . y + = theme_cache . v_separation / 2 ;
2022-02-15 18:06:48 +01:00
if ( rtl ) {
2024-06-02 03:15:16 +02:00
draw_pos . x = size . width - draw_pos . x - tag_icon_size . x ;
2020-05-14 16:41:43 +02:00
}
2024-06-02 03:15:16 +02:00
draw_texture_rect ( items [ i ] . tag_icon , Rect2 ( draw_pos + base_ofs , tag_icon_size ) ) ;
2022-02-15 18:06:48 +01:00
}
2015-06-06 14:44:38 +02:00
2022-02-15 18:06:48 +01:00
if ( ! items [ i ] . text . is_empty ( ) ) {
int max_len = - 1 ;
Vector2 size2 = items [ i ] . text_buf - > get_size ( ) ;
if ( fixed_column_width ) {
max_len = fixed_column_width ;
} else if ( same_column_width ) {
max_len = items [ i ] . rect_cache . size . x ;
2015-06-06 14:44:38 +02:00
} else {
2022-02-15 18:06:48 +01:00
max_len = size2 . x ;
2015-06-06 14:44:38 +02:00
}
2023-03-10 19:28:35 +01:00
Color txt_modulate ;
if ( items [ i ] . selected ) {
txt_modulate = theme_cache . font_selected_color ;
} else if ( hovered = = i ) {
txt_modulate = theme_cache . font_hovered_color ;
} else if ( items [ i ] . custom_fg ! = Color ( ) ) {
txt_modulate = items [ i ] . custom_fg ;
} else {
txt_modulate = theme_cache . font_color ;
}
2022-02-15 18:06:48 +01:00
if ( items [ i ] . disabled ) {
2022-09-29 11:53:28 +02:00
txt_modulate . a * = 0.5 ;
2020-09-03 13:22:16 +02:00
}
2022-02-15 18:06:48 +01:00
if ( icon_mode = = ICON_MODE_TOP & & max_text_lines > 0 ) {
text_ofs + = base_ofs ;
text_ofs + = items [ i ] . rect_cache . position ;
2020-09-03 13:22:16 +02:00
2024-02-14 23:45:49 +01:00
text_ofs . x + = theme_cache . h_separation / 2 ;
text_ofs . y + = theme_cache . v_separation / 2 ;
2022-02-15 18:06:48 +01:00
if ( rtl ) {
text_ofs . x = size . width - text_ofs . x - max_len ;
}
items . write [ i ] . text_buf - > set_alignment ( HORIZONTAL_ALIGNMENT_CENTER ) ;
2024-02-14 23:45:49 +01:00
float text_w = items [ i ] . rect_cache . size . width - theme_cache . h_separation ;
items . write [ i ] . text_buf - > set_width ( text_w ) ;
2022-08-31 14:02:40 +02:00
if ( theme_cache . font_outline_size > 0 & & theme_cache . font_outline_color . a > 0 ) {
items [ i ] . text_buf - > draw_outline ( get_canvas_item ( ) , text_ofs , theme_cache . font_outline_size , theme_cache . font_outline_color ) ;
2022-02-15 18:06:48 +01:00
}
2022-09-29 11:53:28 +02:00
items [ i ] . text_buf - > draw ( get_canvas_item ( ) , text_ofs , txt_modulate ) ;
2020-09-03 13:22:16 +02:00
} else {
2022-02-15 18:06:48 +01:00
if ( fixed_column_width > 0 ) {
size2 . x = MIN ( size2 . x , fixed_column_width ) ;
}
if ( icon_mode = = ICON_MODE_TOP ) {
text_ofs . x + = ( items [ i ] . rect_cache . size . width - size2 . x ) / 2 ;
2024-02-14 23:45:49 +01:00
text_ofs . x + = theme_cache . h_separation / 2 ;
text_ofs . y + = theme_cache . v_separation / 2 ;
2022-02-15 18:06:48 +01:00
} else {
text_ofs . y + = ( items [ i ] . rect_cache . size . height - size2 . y ) / 2 ;
2024-02-14 23:45:49 +01:00
text_ofs . x + = theme_cache . h_separation / 2 ;
2022-02-15 18:06:48 +01:00
}
text_ofs + = base_ofs ;
text_ofs + = items [ i ] . rect_cache . position ;
2024-02-14 23:45:49 +01:00
float text_w = width - text_ofs . x - theme_cache . h_separation ;
2023-05-17 19:48:57 +02:00
items . write [ i ] . text_buf - > set_width ( text_w ) ;
2022-02-15 18:06:48 +01:00
if ( rtl ) {
2023-05-17 19:48:57 +02:00
text_ofs . x = size . width - width ;
2022-02-15 18:06:48 +01:00
items . write [ i ] . text_buf - > set_alignment ( HORIZONTAL_ALIGNMENT_RIGHT ) ;
} else {
items . write [ i ] . text_buf - > set_alignment ( HORIZONTAL_ALIGNMENT_LEFT ) ;
}
2022-08-31 14:02:40 +02:00
if ( theme_cache . font_outline_size > 0 & & theme_cache . font_outline_color . a > 0 ) {
items [ i ] . text_buf - > draw_outline ( get_canvas_item ( ) , text_ofs , theme_cache . font_outline_size , theme_cache . font_outline_color ) ;
2022-02-15 18:06:48 +01:00
}
2022-02-23 21:31:51 +01:00
if ( width - text_ofs . x > 0 ) {
2022-09-29 11:53:28 +02:00
items [ i ] . text_buf - > draw ( get_canvas_item ( ) , text_ofs , txt_modulate ) ;
2022-02-23 21:31:51 +01:00
}
2020-09-03 13:22:16 +02:00
}
2022-02-15 18:06:48 +01:00
}
if ( select_mode = = SELECT_MULTI & & i = = current ) {
Rect2 r = rcache ;
r . position + = base_ofs ;
2020-12-25 22:45:28 +01:00
2022-02-15 18:06:48 +01:00
if ( rtl ) {
r . position . x = size . width - r . position . x - r . size . x ;
2020-12-25 22:45:28 +01:00
}
2022-02-15 18:06:48 +01:00
draw_style_box ( cursor , r ) ;
2015-06-06 14:44:38 +02:00
}
}
2022-02-15 18:06:48 +01:00
} break ;
2015-06-06 14:44:38 +02:00
}
}
2022-07-29 18:49:14 +02:00
void ItemList : : force_update_list_size ( ) {
2023-03-09 12:57:59 +01:00
if ( ! shape_changed ) {
return ;
}
int scroll_bar_minwidth = scroll_bar - > get_minimum_size ( ) . x ;
Size2 size = get_size ( ) ;
float max_column_width = 0.0 ;
//1- compute item minimum sizes
for ( int i = 0 ; i < items . size ( ) ; i + + ) {
Size2 minsize ;
if ( items [ i ] . icon . is_valid ( ) ) {
if ( fixed_icon_size . x > 0 & & fixed_icon_size . y > 0 ) {
minsize = fixed_icon_size * icon_scale ;
} else {
minsize = items [ i ] . get_icon_size ( ) * icon_scale ;
}
if ( ! items [ i ] . text . is_empty ( ) ) {
if ( icon_mode = = ICON_MODE_TOP ) {
minsize . y + = theme_cache . icon_margin ;
} else {
minsize . x + = theme_cache . icon_margin ;
}
}
}
if ( ! items [ i ] . text . is_empty ( ) ) {
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 ) ;
Size2 s = items [ i ] . text_buf - > get_size ( ) ;
if ( icon_mode = = ICON_MODE_TOP ) {
minsize . x = MAX ( minsize . x , s . width ) ;
if ( max_text_lines > 0 ) {
minsize . y + = s . height + theme_cache . line_separation * max_text_lines ;
} else {
minsize . y + = s . height ;
}
} else {
minsize . y = MAX ( minsize . y , s . height ) ;
minsize . x + = s . width ;
}
}
if ( fixed_column_width > 0 ) {
minsize . x = fixed_column_width ;
}
max_column_width = MAX ( max_column_width , minsize . x ) ;
2024-02-14 23:45:49 +01:00
// Elements need to adapt to the selected size.
2023-03-09 12:57:59 +01:00
minsize . y + = theme_cache . v_separation ;
minsize . x + = theme_cache . h_separation ;
2024-02-14 23:45:49 +01:00
2023-03-09 12:57:59 +01:00
items . write [ i ] . rect_cache . size = minsize ;
items . write [ i ] . min_rect_cache . size = minsize ;
}
int fit_size = size . x - theme_cache . panel_style - > get_minimum_size ( ) . width - scroll_bar_minwidth ;
//2-attempt best fit
current_columns = 0x7FFFFFFF ;
if ( max_columns > 0 ) {
current_columns = max_columns ;
}
// Repeat until all items fit.
while ( true ) {
bool all_fit = true ;
Vector2 ofs ;
int col = 0 ;
int max_h = 0 ;
separators . clear ( ) ;
for ( int i = 0 ; i < items . size ( ) ; i + + ) {
if ( current_columns > 1 & & items [ i ] . rect_cache . size . width + ofs . x > fit_size ) {
// Went past.
current_columns = MAX ( col , 1 ) ;
all_fit = false ;
break ;
}
if ( same_column_width ) {
2024-02-14 23:45:49 +01:00
items . write [ i ] . rect_cache . size . x = max_column_width + theme_cache . h_separation ;
2023-03-09 12:57:59 +01:00
}
items . write [ i ] . rect_cache . position = ofs ;
max_h = MAX ( max_h , items [ i ] . rect_cache . size . y ) ;
2024-02-14 23:45:49 +01:00
ofs . x + = items [ i ] . rect_cache . size . x ;
2023-03-09 12:57:59 +01:00
items . write [ i ] . column = col ;
col + + ;
if ( col = = current_columns ) {
if ( i < items . size ( ) - 1 ) {
2024-02-14 23:45:49 +01:00
separators . push_back ( ofs . y + max_h ) ;
2023-03-09 12:57:59 +01:00
}
for ( int j = i ; j > = 0 & & col > 0 ; j - - , col - - ) {
items . write [ j ] . rect_cache . size . y = max_h ;
}
ofs . x = 0 ;
2024-02-14 23:45:49 +01:00
ofs . y + = max_h ;
2023-03-09 12:57:59 +01:00
col = 0 ;
max_h = 0 ;
}
}
if ( all_fit ) {
2023-11-10 19:50:58 +01:00
for ( int j = items . size ( ) - 1 ; j > = 0 & & col > 0 ; j - - , col - - ) {
items . write [ j ] . rect_cache . size . y = max_h ;
}
2023-03-09 12:57:59 +01:00
float page = MAX ( 0 , size . height - theme_cache . panel_style - > get_minimum_size ( ) . height ) ;
float max = MAX ( page , ofs . y + max_h ) ;
if ( auto_height ) {
auto_height_value = ofs . y + max_h + theme_cache . panel_style - > get_minimum_size ( ) . height ;
}
scroll_bar - > set_max ( max ) ;
scroll_bar - > set_page ( page ) ;
if ( max < = page ) {
scroll_bar - > set_value ( 0 ) ;
scroll_bar - > hide ( ) ;
} else {
scroll_bar - > show ( ) ;
if ( do_autoscroll_to_bottom ) {
scroll_bar - > set_value ( max ) ;
}
}
break ;
}
}
update_minimum_size ( ) ;
shape_changed = false ;
}
2015-06-06 14:44:38 +02:00
void ItemList : : _scroll_changed ( double ) {
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
2015-06-06 14:44:38 +02:00
}
2023-03-10 19:28:35 +01:00
void ItemList : : _mouse_exited ( ) {
if ( hovered > - 1 ) {
hovered = - 1 ;
queue_redraw ( ) ;
}
}
2017-09-10 15:37:49 +02:00
int ItemList : : get_item_at_position ( const Point2 & p_pos , bool p_exact ) const {
2015-06-06 14:44:38 +02:00
Vector2 pos = p_pos ;
2022-09-06 19:09:32 +02:00
pos - = theme_cache . panel_style - > get_offset ( ) ;
2017-01-04 05:16:14 +01:00
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 ;
int closest_dist = 0x7FFFFFFF ;
for ( int i = 0 ; i < items . size ( ) ; i + + ) {
Rect2 rc = items [ i ] . rect_cache ;
2024-02-15 00:15:35 +01:00
2015-06-06 14:44:38 +02:00
if ( i % current_columns = = current_columns - 1 ) {
2022-09-21 15:37:01 +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 ) ) {
closest = i ;
break ;
}
float dist = rc . distance_to ( pos ) ;
2016-05-15 04:48:23 +02:00
if ( ! p_exact & & dist < closest_dist ) {
2015-06-06 14:44:38 +02:00
closest = i ;
closest_dist = dist ;
}
}
2016-05-11 16:46:08 +02:00
return closest ;
}
2017-02-20 03:19:30 +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
Vector2 pos = p_pos ;
2022-09-06 19:09:32 +02:00
pos - = theme_cache . panel_style - > get_offset ( ) ;
2017-02-20 03:19:30 +01:00
pos . y + = scroll_bar - > get_value ( ) ;
2020-09-03 13:22:16 +02:00
if ( is_layout_rtl ( ) ) {
pos . x = get_size ( ) . width - pos . x ;
}
2017-02-20 03:19:30 +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
}
2016-05-11 16:46:08 +02: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
2015-06-06 14:44:38 +02:00
if ( closest ! = - 1 ) {
2016-09-07 17:21:20 +02:00
if ( ! items [ closest ] . tooltip_enabled ) {
return " " ;
}
2021-12-09 10:42:46 +01:00
if ( ! items [ closest ] . tooltip . is_empty ( ) ) {
2015-06-06 14:44:38 +02:00
return items [ closest ] . tooltip ;
}
2021-12-09 10:42:46 +01:00
if ( ! items [ closest ] . text . is_empty ( ) ) {
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 ( ) ;
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
2016-07-22 07:45:52 +02:00
shape_changed = true ;
2015-06-22 05:03:19 +02:00
if ( select_mode = = SELECT_SINGLE ) {
for ( int i = 0 ; i < items . size ( ) ; i + + ) {
if ( items [ i ] . selected ) {
select ( i ) ;
return ;
}
}
}
}
int ItemList : : find_metadata ( const Variant & p_metadata ) const {
for ( int i = 0 ; i < items . size ( ) ; i + + ) {
if ( items [ i ] . metadata = = p_metadata ) {
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 ) {
allow_rmb_select = p_allow ;
}
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 ;
}
2023-04-18 08:50:24 +02:00
void ItemList : : set_allow_search ( bool p_allow ) {
allow_search = p_allow ;
}
bool ItemList : : get_allow_search ( ) const {
return allow_search ;
}
2016-05-27 18:54:46 +02:00
void ItemList : : set_icon_scale ( real_t p_scale ) {
2022-12-13 08:38:33 +01:00
ERR_FAIL_COND ( ! Math : : is_finite ( p_scale ) ) ;
2023-09-03 13:10:24 +02:00
if ( icon_scale = = p_scale ) {
return ;
}
2016-05-27 18:54:46 +02:00
icon_scale = p_scale ;
2023-09-03 13:10:24 +02:00
queue_redraw ( ) ;
shape_changed = true ;
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 ) ;
2024-01-28 21:51:39 +01:00
if ( select_mode = = SELECT_SINGLE ) {
2016-06-28 19:09:17 +02:00
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-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 ) {
2022-03-16 08:50:48 +01:00
if ( auto_height = = p_enable ) {
return ;
}
2017-07-21 08:17:06 +02:00
auto_height = p_enable ;
shape_changed = true ;
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
2017-07-21 08:17:06 +02:00
}
bool ItemList : : has_auto_height ( ) const {
return auto_height ;
}
2022-06-15 10:01:45 +02:00
void ItemList : : set_text_overrun_behavior ( TextServer : : OverrunBehavior p_behavior ) {
2021-08-21 00:22:09 +02:00
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 ;
2022-08-13 23:21:24 +02:00
queue_redraw ( ) ;
2021-08-21 00:22:09 +02:00
}
}
2022-06-15 10:01:45 +02:00
TextServer : : OverrunBehavior ItemList : : get_text_overrun_behavior ( ) const {
2021-08-21 00:22:09 +02:00
return text_overrun_behavior ;
}
2021-10-27 18:29:44 +02:00
bool ItemList : : _set ( const StringName & p_name , const Variant & p_value ) {
2023-11-08 23:16:17 +01:00
if ( property_helper . property_set_value ( p_name , p_value ) ) {
return true ;
2021-10-27 18:29:44 +02:00
}
2023-11-08 23:16:17 +01:00
2021-10-27 18:29:44 +02:00
# ifndef DISABLE_DEPRECATED
// Compatibility.
if ( p_name = = " items " ) {
Array arr = p_value ;
ERR_FAIL_COND_V ( arr . size ( ) % 3 , false ) ;
clear ( ) ;
for ( int i = 0 ; i < arr . size ( ) ; i + = 3 ) {
String text = arr [ i + 0 ] ;
Ref < Texture2D > icon = arr [ i + 1 ] ;
bool disabled = arr [ i + 2 ] ;
int idx = get_item_count ( ) ;
add_item ( text , icon ) ;
set_item_disabled ( idx , disabled ) ;
}
}
# endif
return false ;
}
2015-06-06 14:44:38 +02: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-02-13 12:47:24 +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_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-02-13 12:47:24 +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-02-13 12:47:24 +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-02-13 12:47:24 +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-02-13 12:47:24 +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-02-13 12:47:24 +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 ) ;
2023-05-08 09:57:49 +02:00
ClassDB : : bind_method ( D_METHOD ( " get_item_rect " , " idx " , " expand " ) , & ItemList : : get_item_rect , DEFVAL ( true ) ) ;
2017-02-13 12:47:24 +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-02-13 12:47:24 +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-02-13 12:47:24 +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-02-13 12:47:24 +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
2021-11-04 15:27:23 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_item_count " , " count " ) , & ItemList : : set_item_count ) ;
2017-02-13 12:47:24 +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-02-13 12:47:24 +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-02-13 12:47:24 +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-02-13 12:47:24 +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-02-13 12:47:24 +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-02-13 12:47:24 +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-02-13 12:47:24 +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-02-13 12:47:24 +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-02-13 12:47:24 +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-02-13 12:47:24 +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-02-13 12:47:24 +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 ) ;
2023-04-18 08:50:24 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_allow_search " , " allow " ) , & ItemList : : set_allow_search ) ;
ClassDB : : bind_method ( D_METHOD ( " get_allow_search " ) , & ItemList : : get_allow_search ) ;
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-02-13 12:47:24 +01:00
ClassDB : : bind_method ( D_METHOD ( " ensure_current_is_visible " ) , & ItemList : : ensure_current_is_visible ) ;
2016-05-11 16:46:08 +02:00
2021-11-30 17:46:36 +01:00
ClassDB : : bind_method ( D_METHOD ( " get_v_scroll_bar " ) , & ItemList : : get_v_scroll_bar ) ;
2015-06-06 14:44:38 +02:00
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 ) ;
2022-07-29 18:49:14 +02:00
ClassDB : : bind_method ( D_METHOD ( " force_update_list_size " ) , & ItemList : : force_update_list_size ) ;
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 " ) ;
2023-04-18 08:50:24 +02:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " allow_search " ) , " set_allow_search " , " get_allow_search " ) ;
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 " ) ;
2021-12-07 04:09:31 +01:00
ADD_ARRAY_COUNT ( " Items " , " item_count " , " set_item_count " , " get_item_count " , " item_ " ) ;
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 " ) ;
2022-05-20 07:24:41 +02:00
ADD_PROPERTY ( PropertyInfo ( Variant : : INT , " fixed_column_width " , PROPERTY_HINT_RANGE , " 0,100,1,or_greater,suffix:px " ) , " 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 " ) ;
2022-08-13 19:22:07 +02:00
ADD_PROPERTY ( PropertyInfo ( Variant : : VECTOR2I , " fixed_icon_size " , PROPERTY_HINT_NONE , " suffix:px " ) , " 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
ADD_SIGNAL ( MethodInfo ( " item_selected " , PropertyInfo ( Variant : : INT , " index " ) ) ) ;
2021-11-26 00:53:27 +01:00
ADD_SIGNAL ( MethodInfo ( " empty_clicked " , PropertyInfo ( Variant : : VECTOR2 , " at_position " ) , PropertyInfo ( Variant : : INT , " mouse_button_index " ) ) ) ;
ADD_SIGNAL ( MethodInfo ( " item_clicked " , PropertyInfo ( Variant : : INT , " index " ) , PropertyInfo ( Variant : : VECTOR2 , " at_position " ) , PropertyInfo ( Variant : : INT , " mouse_button_index " ) ) ) ;
2015-06-06 14:44:38 +02:00
ADD_SIGNAL ( MethodInfo ( " multi_selected " , PropertyInfo ( Variant : : INT , " index " ) , PropertyInfo ( Variant : : BOOL , " selected " ) ) ) ;
ADD_SIGNAL ( MethodInfo ( " item_activated " , PropertyInfo ( Variant : : INT , " index " ) ) ) ;
2023-09-08 21:00:10 +02:00
BIND_THEME_ITEM ( Theme : : DATA_TYPE_CONSTANT , ItemList , h_separation ) ;
BIND_THEME_ITEM ( Theme : : DATA_TYPE_CONSTANT , ItemList , v_separation ) ;
BIND_THEME_ITEM_CUSTOM ( Theme : : DATA_TYPE_STYLEBOX , ItemList , panel_style , " panel " ) ;
BIND_THEME_ITEM_CUSTOM ( Theme : : DATA_TYPE_STYLEBOX , ItemList , focus_style , " focus " ) ;
BIND_THEME_ITEM ( Theme : : DATA_TYPE_FONT , ItemList , font ) ;
BIND_THEME_ITEM ( Theme : : DATA_TYPE_FONT_SIZE , ItemList , font_size ) ;
BIND_THEME_ITEM ( Theme : : DATA_TYPE_COLOR , ItemList , font_color ) ;
BIND_THEME_ITEM ( Theme : : DATA_TYPE_COLOR , ItemList , font_hovered_color ) ;
BIND_THEME_ITEM ( Theme : : DATA_TYPE_COLOR , ItemList , font_selected_color ) ;
BIND_THEME_ITEM_CUSTOM ( Theme : : DATA_TYPE_CONSTANT , ItemList , font_outline_size , " outline_size " ) ;
BIND_THEME_ITEM ( Theme : : DATA_TYPE_COLOR , ItemList , font_outline_color ) ;
BIND_THEME_ITEM ( Theme : : DATA_TYPE_CONSTANT , ItemList , line_separation ) ;
BIND_THEME_ITEM ( Theme : : DATA_TYPE_CONSTANT , ItemList , icon_margin ) ;
BIND_THEME_ITEM_CUSTOM ( Theme : : DATA_TYPE_STYLEBOX , ItemList , hovered_style , " hovered " ) ;
BIND_THEME_ITEM_CUSTOM ( Theme : : DATA_TYPE_STYLEBOX , ItemList , selected_style , " selected " ) ;
BIND_THEME_ITEM_CUSTOM ( Theme : : DATA_TYPE_STYLEBOX , ItemList , selected_focus_style , " selected_focus " ) ;
BIND_THEME_ITEM_CUSTOM ( Theme : : DATA_TYPE_STYLEBOX , ItemList , cursor_style , " cursor_unfocused " ) ;
BIND_THEME_ITEM_CUSTOM ( Theme : : DATA_TYPE_STYLEBOX , ItemList , cursor_focus_style , " cursor " ) ;
BIND_THEME_ITEM ( Theme : : DATA_TYPE_COLOR , ItemList , guide_color ) ;
2023-11-08 23:16:17 +01:00
Item defaults ( true ) ;
base_property_helper . set_prefix ( " item_ " ) ;
2024-05-09 14:19:16 +02:00
base_property_helper . set_array_length_getter ( & ItemList : : get_item_count ) ;
2024-02-11 12:09:55 +01:00
base_property_helper . register_property ( PropertyInfo ( Variant : : STRING , " text " ) , defaults . text , & ItemList : : set_item_text , & ItemList : : get_item_text ) ;
base_property_helper . register_property ( PropertyInfo ( Variant : : OBJECT , " icon " , PROPERTY_HINT_RESOURCE_TYPE , " Texture2D " ) , defaults . icon , & ItemList : : set_item_icon , & ItemList : : get_item_icon ) ;
base_property_helper . register_property ( PropertyInfo ( Variant : : BOOL , " selectable " ) , defaults . selectable , & ItemList : : set_item_selectable , & ItemList : : is_item_selectable ) ;
base_property_helper . register_property ( PropertyInfo ( Variant : : BOOL , " disabled " ) , defaults . disabled , & ItemList : : set_item_disabled , & ItemList : : is_item_disabled ) ;
2024-07-03 09:39:18 +02:00
PropertyListHelper : : register_base_helper ( & base_property_helper ) ;
2015-06-06 14:44:38 +02:00
}
ItemList : : ItemList ( ) {
scroll_bar = memnew ( VScrollBar ) ;
2021-08-25 15:49:30 +02:00
add_child ( scroll_bar , false , INTERNAL_MODE_FRONT ) ;
2024-05-14 11:42:00 +02:00
scroll_bar - > connect ( SceneStringName ( value_changed ) , callable_mp ( this , & ItemList : : _scroll_changed ) ) ;
2015-06-06 14:44:38 +02:00
2024-05-13 16:56:03 +02:00
connect ( SceneStringName ( mouse_exited ) , callable_mp ( this , & ItemList : : _mouse_exited ) ) ;
2023-03-10 19:28:35 +01:00
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 ) ;
2023-11-08 23:16:17 +01:00
property_helper . setup_for_instance ( base_property_helper , this ) ;
2015-06-06 14:44:38 +02:00
}
ItemList : : ~ ItemList ( ) {
}