Merge pull request #90411 from kitbdev/multisplit
Allow SplitContainer to have more than two children
This commit is contained in:
@ -1,10 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="SplitContainer" inherits="Container" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
|
||||
<brief_description>
|
||||
A container that splits two child controls horizontally or vertically and provides a grabber for adjusting the split ratio.
|
||||
A container that arranges child controls horizontally or vertically and provides grabbers for adjusting the split ratios between them.
|
||||
</brief_description>
|
||||
<description>
|
||||
A container that accepts only two child controls, then arranges them horizontally or vertically and creates a divisor between them. The divisor can be dragged around to change the size relation between the child controls.
|
||||
A container that arranges child controls horizontally or vertically and creates grabbers between them. The grabbers can be dragged around to change the size relations between the child controls.
|
||||
</description>
|
||||
<tutorials>
|
||||
<link title="Using Containers">$DOCS_URL/tutorials/ui/gui_containers.html</link>
|
||||
@ -12,11 +12,12 @@
|
||||
<methods>
|
||||
<method name="clamp_split_offset">
|
||||
<return type="void" />
|
||||
<param index="0" name="priority_index" type="int" default="0" />
|
||||
<description>
|
||||
Clamps the [member split_offset] value to not go outside the currently possible minimal and maximum values.
|
||||
Clamps the [member split_offsets] values to ensure they are within valid ranges and do not overlap with each other. When overlaps occur, this method prioritizes one split offset (at index [param priority_index]) by clamping any overlapping split offsets to it.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_drag_area_control">
|
||||
<method name="get_drag_area_control" deprecated="Use the first element of [method get_drag_area_controls] instead.">
|
||||
<return type="Control" />
|
||||
<description>
|
||||
Returns the drag area [Control]. For example, you can move a pre-configured button into the drag area [Control] so that it rides along with the split bar. Try setting the [Button] anchors to [code]center[/code] prior to the [code]reparent()[/code] call.
|
||||
@ -27,10 +28,21 @@
|
||||
[b]Warning:[/b] This is a required internal node, removing and freeing it may cause a crash.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_drag_area_controls">
|
||||
<return type="Control[]" />
|
||||
<description>
|
||||
Returns an [Array] of the drag area [Control]s. These are the interactable [Control] nodes between each child. For example, this can be used to add a pre-configured button to a drag area [Control] so that it rides along with the split bar. Try setting the [Button] anchors to [code]center[/code] prior to the [method Node.reparent] call.
|
||||
[codeblock]
|
||||
$BarnacleButton.reparent($SplitContainer.get_drag_area_controls()[0])
|
||||
[/codeblock]
|
||||
[b]Note:[/b] The drag area [Control]s are drawn over the [SplitContainer]'s children, so [CanvasItem] draw objects called from a drag area and children added to it will also appear over the [SplitContainer]'s children. Try setting [member Control.mouse_filter] of custom children to [constant Control.MOUSE_FILTER_IGNORE] to prevent blocking the mouse from dragging if desired.
|
||||
[b]Warning:[/b] These are required internal nodes, removing or freeing them may cause a crash.
|
||||
</description>
|
||||
</method>
|
||||
</methods>
|
||||
<members>
|
||||
<member name="collapsed" type="bool" setter="set_collapsed" getter="is_collapsed" default="false">
|
||||
If [code]true[/code], the dragger will be disabled and the children will be sized as if the [member split_offset] was [code]0[/code].
|
||||
If [code]true[/code], the draggers will be disabled and the children will be sized as if all [member split_offsets] were [code]0[/code].
|
||||
</member>
|
||||
<member name="drag_area_highlight_in_editor" type="bool" setter="set_drag_area_highlight_in_editor" getter="is_drag_area_highlight_in_editor_enabled" default="false">
|
||||
Highlights the drag area [Rect2] so you can see where it is during development. The drag area is gold if [member dragging_enabled] is [code]true[/code], and red if [code]false[/code].
|
||||
@ -50,8 +62,13 @@
|
||||
<member name="dragging_enabled" type="bool" setter="set_dragging_enabled" getter="is_dragging_enabled" default="true">
|
||||
Enables or disables split dragging.
|
||||
</member>
|
||||
<member name="split_offset" type="int" setter="set_split_offset" getter="get_split_offset" default="0">
|
||||
The initial offset of the splitting between the two [Control]s, with [code]0[/code] being at the end of the first [Control].
|
||||
<member name="split_offset" type="int" setter="set_split_offset" getter="get_split_offset" default="0" deprecated="Use [member split_offsets] instead. The first element of the array is the split offset between the first two children.">
|
||||
The first element of [member split_offsets].
|
||||
</member>
|
||||
<member name="split_offsets" type="PackedInt32Array" setter="set_split_offsets" getter="get_split_offsets" default="PackedInt32Array(0)">
|
||||
Offsets for each dragger in pixels. Each one is the offset of the split between the [Control] nodes before and after the dragger, with [code]0[/code] being the default position. The default position is based on the [Control] nodes expand flags and minimum sizes. See [member Control.size_flags_horizontal], [member Control.size_flags_vertical], and [member Control.size_flags_stretch_ratio].
|
||||
If none of the [Control] nodes before the dragger are expanded, the default position will be at the start of the [SplitContainer]. If none of the [Control] nodes after the dragger are expanded, the default position will be at the end of the [SplitContainer]. If the dragger is in between expanded [Control] nodes, the default position will be in the middle, based on the [member Control.size_flags_stretch_ratio]s and minimum sizes.
|
||||
[b]Note:[/b] If the split offsets cause [Control] nodes to overlap, the first split will take priority when resolving the positions.
|
||||
</member>
|
||||
<member name="touch_dragger_enabled" type="bool" setter="set_touch_dragger_enabled" getter="is_touch_dragger_enabled" default="false">
|
||||
If [code]true[/code], a touch-friendly drag handle will be enabled for better usability on smaller screens. Unlike the standard grabber, this drag handle overlaps the [SplitContainer]'s children and does not affect their minimum separation. The standard grabber will no longer be drawn when this option is enabled.
|
||||
@ -75,7 +92,7 @@
|
||||
<signal name="dragged">
|
||||
<param index="0" name="offset" type="int" />
|
||||
<description>
|
||||
Emitted when the dragger is dragged by user.
|
||||
Emitted when any dragger is dragged by user.
|
||||
</description>
|
||||
</signal>
|
||||
</signals>
|
||||
@ -104,20 +121,20 @@
|
||||
The color of the touch dragger when pressed.
|
||||
</theme_item>
|
||||
<theme_item name="autohide" data_type="constant" type="int" default="1">
|
||||
Boolean value. If [code]1[/code] ([code]true[/code]), the grabber will hide automatically when it isn't under the cursor. If [code]0[/code] ([code]false[/code]), it's always visible. The [member dragger_visibility] must be [constant DRAGGER_VISIBLE].
|
||||
Boolean value. If [code]1[/code] ([code]true[/code]), the grabbers will hide automatically when they aren't under the cursor. If [code]0[/code] ([code]false[/code]), the grabbers are always visible. The [member dragger_visibility] must be [constant DRAGGER_VISIBLE].
|
||||
</theme_item>
|
||||
<theme_item name="minimum_grab_thickness" data_type="constant" type="int" default="6">
|
||||
The minimum thickness of the area users can click on to grab the split bar. This ensures that the split bar can still be dragged if [theme_item separation] or [theme_item h_grabber] / [theme_item v_grabber]'s size is too narrow to easily select.
|
||||
The minimum thickness of the area users can click on to grab a split bar. This ensures that the split bar can still be dragged if [theme_item separation] or [theme_item h_grabber] / [theme_item v_grabber]'s size is too narrow to easily select.
|
||||
</theme_item>
|
||||
<theme_item name="separation" data_type="constant" type="int" default="12">
|
||||
The split bar thickness, i.e., the gap between the two children of the container. This is overridden by the size of the grabber icon if [member dragger_visibility] is set to [constant DRAGGER_VISIBLE], or [constant DRAGGER_HIDDEN], and [theme_item separation] is smaller than the size of the grabber icon in the same axis.
|
||||
The split bar thickness, i.e., the gap between each child of the container. This is overridden by the size of the grabber icon if [member dragger_visibility] is set to [constant DRAGGER_VISIBLE], or [constant DRAGGER_HIDDEN], and [theme_item separation] is smaller than the size of the grabber icon in the same axis.
|
||||
[b]Note:[/b] To obtain [theme_item separation] values less than the size of the grabber icon, for example a [code]1 px[/code] hairline, set [theme_item h_grabber] or [theme_item v_grabber] to a new [ImageTexture], which effectively sets the grabber icon size to [code]0 px[/code].
|
||||
</theme_item>
|
||||
<theme_item name="grabber" data_type="icon" type="Texture2D">
|
||||
The icon used for the grabber drawn in the middle area. This is only used in [HSplitContainer] and [VSplitContainer]. For [SplitContainer], see [theme_item h_grabber] and [theme_item v_grabber] instead.
|
||||
The icon used for the grabbers drawn in the separations. This is only used in [HSplitContainer] and [VSplitContainer]. For [SplitContainer], see [theme_item h_grabber] and [theme_item v_grabber] instead.
|
||||
</theme_item>
|
||||
<theme_item name="h_grabber" data_type="icon" type="Texture2D">
|
||||
The icon used for the grabber drawn in the middle area when [member vertical] is [code]false[/code].
|
||||
The icon used for the grabbers drawn in the separations when [member vertical] is [code]false[/code].
|
||||
</theme_item>
|
||||
<theme_item name="h_touch_dragger" data_type="icon" type="Texture2D">
|
||||
The icon used for the drag handle when [member touch_dragger_enabled] is [code]true[/code] and [member vertical] is [code]false[/code].
|
||||
@ -126,7 +143,7 @@
|
||||
The icon used for the drag handle when [member touch_dragger_enabled] is [code]true[/code]. This is only used in [HSplitContainer] and [VSplitContainer]. For [SplitContainer], see [theme_item h_touch_dragger] and [theme_item v_touch_dragger] instead.
|
||||
</theme_item>
|
||||
<theme_item name="v_grabber" data_type="icon" type="Texture2D">
|
||||
The icon used for the grabber drawn in the middle area when [member vertical] is [code]true[/code].
|
||||
The icon used for the grabbers drawn in the separations when [member vertical] is [code]true[/code].
|
||||
</theme_item>
|
||||
<theme_item name="v_touch_dragger" data_type="icon" type="Texture2D">
|
||||
The icon used for the drag handle when [member touch_dragger_enabled] is [code]true[/code] and [member vertical] is [code]true[/code].
|
||||
|
||||
@ -106,3 +106,10 @@ GH-112379
|
||||
Validate extension JSON: Error: Field 'classes/DisplayServer/methods/tts_speak/arguments/5': meta changed value in new API, from "int32" to "int64".
|
||||
|
||||
`utterance_id` argument changed from `int32` to `int64`. No compatibility method needed.
|
||||
|
||||
|
||||
GH-90411
|
||||
--------
|
||||
Validate extension JSON: JSON file: Field was added in a way that breaks compatibility 'classes/SplitContainer/methods/clamp_split_offset': arguments
|
||||
|
||||
Optional argument added for index. Compatibility method registered.
|
||||
|
||||
41
scene/gui/split_container.compat.inc
Normal file
41
scene/gui/split_container.compat.inc
Normal file
@ -0,0 +1,41 @@
|
||||
/**************************************************************************/
|
||||
/* split_container.compat.inc */
|
||||
/**************************************************************************/
|
||||
/* 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. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef DISABLE_DEPRECATED
|
||||
|
||||
void SplitContainer::_clamp_split_offset_compat_90411() {
|
||||
clamp_split_offset(0);
|
||||
}
|
||||
|
||||
void SplitContainer::_bind_compatibility_methods() {
|
||||
ClassDB::bind_compatibility_method(D_METHOD("clamp_split_offset"), &SplitContainer::_clamp_split_offset_compat_90411);
|
||||
}
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@ -37,7 +37,12 @@ class TextureRect;
|
||||
class SplitContainerDragger : public Control {
|
||||
GDCLASS(SplitContainerDragger, Control);
|
||||
friend class SplitContainer;
|
||||
|
||||
Rect2 split_bar_rect;
|
||||
TextureRect *touch_dragger = nullptr;
|
||||
|
||||
void _touch_dragger_mouse_exited();
|
||||
void _touch_dragger_gui_input(const Ref<InputEvent> &p_event);
|
||||
|
||||
protected:
|
||||
void _notification(int p_what);
|
||||
@ -50,12 +55,18 @@ protected:
|
||||
private:
|
||||
bool dragging = false;
|
||||
int drag_from = 0;
|
||||
int drag_ofs = 0;
|
||||
int start_drag_split_offset = 0;
|
||||
bool mouse_inside = false;
|
||||
|
||||
public:
|
||||
int dragger_index = -1;
|
||||
|
||||
virtual CursorShape get_cursor_shape(const Point2 &p_pos = Point2i()) const override;
|
||||
|
||||
void set_touch_dragger_enabled(bool p_enabled);
|
||||
void update_touch_dragger();
|
||||
bool is_touch_dragger_enabled() const;
|
||||
|
||||
SplitContainerDragger();
|
||||
};
|
||||
|
||||
@ -71,21 +82,26 @@ public:
|
||||
};
|
||||
|
||||
private:
|
||||
int show_drag_area = false;
|
||||
bool show_drag_area = false;
|
||||
int drag_area_margin_begin = 0;
|
||||
int drag_area_margin_end = 0;
|
||||
int drag_area_offset = 0;
|
||||
int split_offset = 0;
|
||||
int computed_split_offset = 0;
|
||||
|
||||
PackedInt32Array split_offsets;
|
||||
LocalVector<int> default_dragger_positions;
|
||||
LocalVector<int> dragger_positions;
|
||||
LocalVector<Control *> valid_children;
|
||||
LocalVector<SplitContainerDragger *> dragging_area_controls;
|
||||
|
||||
bool vertical = false;
|
||||
bool collapsed = false;
|
||||
DraggerVisibility dragger_visibility = DRAGGER_VISIBLE;
|
||||
bool dragging_enabled = true;
|
||||
|
||||
SplitContainerDragger *dragging_area_control = nullptr;
|
||||
bool split_offset_pending = false;
|
||||
bool can_use_desired_sizes = false;
|
||||
bool initialized = false;
|
||||
|
||||
bool touch_dragger_enabled = false;
|
||||
TextureRect *touch_dragger = nullptr;
|
||||
|
||||
struct ThemeCache {
|
||||
Color touch_dragger_color;
|
||||
@ -106,24 +122,44 @@ private:
|
||||
|
||||
Ref<Texture2D> _get_grabber_icon() const;
|
||||
Ref<Texture2D> _get_touch_dragger_icon() const;
|
||||
void _touch_dragger_mouse_exited();
|
||||
void _touch_dragger_gui_input(const Ref<InputEvent> &p_event);
|
||||
void _compute_split_offset(bool p_clamp);
|
||||
Point2i _get_valid_range(int p_dragger_index) const;
|
||||
|
||||
PackedInt32Array _get_desired_sizes() const;
|
||||
void _set_desired_sizes(const PackedInt32Array &p_desired_sizes, int p_priority_index = -1);
|
||||
|
||||
void _update_default_dragger_positions();
|
||||
void _update_dragger_positions(int p_clamp_index = -1);
|
||||
int _get_separation() const;
|
||||
void _resort();
|
||||
Control *_get_sortable_child(int p_idx, SortableVisibilityMode p_visibility_mode = SortableVisibilityMode::VISIBLE_IN_TREE) const;
|
||||
void _update_draggers();
|
||||
void _on_child_visibility_changed(Control *p_control);
|
||||
void _add_valid_child(Control *p_control);
|
||||
void _remove_valid_child(Control *p_control);
|
||||
|
||||
protected:
|
||||
bool is_fixed = false;
|
||||
|
||||
void _notification(int p_what);
|
||||
void _validate_property(PropertyInfo &p_property) const;
|
||||
|
||||
virtual void add_child_notify(Node *p_child) override;
|
||||
virtual void remove_child_notify(Node *p_child) override;
|
||||
virtual void move_child_notify(Node *p_child) override;
|
||||
static void _bind_methods();
|
||||
|
||||
#ifndef DISABLE_DEPRECATED
|
||||
void _clamp_split_offset_compat_90411();
|
||||
static void _bind_compatibility_methods();
|
||||
#endif // DISABLE_DEPRECATED
|
||||
|
||||
public:
|
||||
void set_split_offset(int p_offset);
|
||||
int get_split_offset() const;
|
||||
void clamp_split_offset();
|
||||
void set_split_offset(int p_offset, int p_index = 0);
|
||||
int get_split_offset(int p_index = 0) const;
|
||||
|
||||
void set_split_offsets(const PackedInt32Array &p_offsets);
|
||||
PackedInt32Array get_split_offsets() const;
|
||||
|
||||
void clamp_split_offset(int p_priority_index = 0);
|
||||
|
||||
void set_collapsed(bool p_collapsed);
|
||||
bool is_collapsed() const;
|
||||
@ -154,11 +190,17 @@ public:
|
||||
void set_show_drag_area_enabled(bool p_enabled);
|
||||
bool is_show_drag_area_enabled() const;
|
||||
|
||||
Control *get_drag_area_control() { return dragging_area_control; }
|
||||
TypedArray<Control> get_drag_area_controls();
|
||||
|
||||
void set_touch_dragger_enabled(bool p_enabled);
|
||||
bool is_touch_dragger_enabled() const;
|
||||
|
||||
#ifndef DISABLE_DEPRECATED
|
||||
Control *get_drag_area_control() { return dragging_area_controls[0]; }
|
||||
void _set_split_offset_first(int p_offset) { set_split_offset(p_offset); }
|
||||
int _get_split_offset_first() const { return get_split_offset(); }
|
||||
#endif
|
||||
|
||||
SplitContainer(bool p_vertical = false);
|
||||
};
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user