Skip to content

Commit 354722d

Browse files
committed
Allow ScrollBar to watch ScrollContainer in tree
This `ScrollBar` is allowed to watch the `ScrollContainer` if both are in the tree. That is, according to the `orientation` of this `ScrollBar`, the corresponding `ScrollBar` in the `ScrollContainer` is shared with this `ScrollBar`. This patch will make it easy to replace the `ScrollBar` inside the `ScrollContainer` in the editor: 1. Set the corresponding `*_scroll_mode` in `ScrollContainer` to `SCROLL_MODE_SHOW_NEVER`; 2. Add an extra `ScrollBar` and set its `watch_target_path` to the path of the target `ScrollContainer`.
1 parent 0cf26fb commit 354722d

File tree

3 files changed

+67
-0
lines changed

3 files changed

+67
-0
lines changed

doc/classes/ScrollBar.xml

+13
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,23 @@
88
</description>
99
<tutorials>
1010
</tutorials>
11+
<methods>
12+
<method name="is_watching" qualifiers="const">
13+
<return type="bool" />
14+
<description>
15+
Returns [code]true[/code] if the target [ScrollContainer] is sharing its corresponding internal [ScrollBar] with this [ScrollBar] according to the orientation of this [ScrollBar].
16+
[b]Note:[/b] Share will only be attempted if both nodes are valid and in the tree.
17+
See [method Range.share].
18+
</description>
19+
</method>
20+
</methods>
1121
<members>
1222
<member name="custom_step" type="float" setter="set_custom_step" getter="get_custom_step" default="-1.0">
1323
Overrides the step used when clicking increment and decrement buttons or when using arrow keys when the [ScrollBar] is focused.
1424
</member>
25+
<member name="watch_target_path" type="NodePath" setter="set_watch_target_path" getter="get_watch_target_path" default="NodePath(&quot;&quot;)">
26+
The [NodePath] of the target [ScrollContainer] that the [ScrollBar] tries to watch. See [method is_watching].
27+
</member>
1528
</members>
1629
<signals>
1730
<signal name="scrolling">

scene/gui/scroll_bar.cpp

+45
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include "core/os/keyboard.h"
3434
#include "core/os/os.h"
3535
#include "core/string/print_string.h"
36+
#include "scene/gui/scroll_container.h"
3637
#include "scene/main/window.h"
3738

3839
bool ScrollBar::focus_by_default = false;
@@ -305,6 +306,8 @@ void ScrollBar::_notification(int p_what) {
305306
drag_node->connect("gui_input", callable_mp(this, &ScrollBar::_drag_node_input));
306307
drag_node->connect("tree_exiting", callable_mp(this, &ScrollBar::_drag_node_exit), varray(), CONNECT_ONESHOT);
307308
}
309+
310+
_try_watch();
308311
} break;
309312

310313
case NOTIFICATION_EXIT_TREE: {
@@ -314,6 +317,8 @@ void ScrollBar::_notification(int p_what) {
314317
}
315318

316319
drag_node = nullptr;
320+
321+
watching = false;
317322
} break;
318323

319324
case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
@@ -500,6 +505,41 @@ Size2 ScrollBar::get_minimum_size() const {
500505
return minsize;
501506
}
502507

508+
void ScrollBar::_try_watch() {
509+
if (watch_target_path.is_empty()) {
510+
return;
511+
}
512+
513+
ScrollContainer *watch_target = Object::cast_to<ScrollContainer>(get_node(watch_target_path));
514+
if (watch_target) {
515+
ScrollBar *watch_target_bar = orientation == HORIZONTAL ? Object::cast_to<ScrollBar>(watch_target->get_h_scroll_bar()) : Object::cast_to<ScrollBar>(watch_target->get_v_scroll_bar());
516+
if (watch_target_bar && watch_target_bar != this) {
517+
watch_target_bar->share(this);
518+
watching = true;
519+
}
520+
}
521+
}
522+
523+
void ScrollBar::set_watch_target_path(const NodePath p_path) {
524+
if (watch_target_path == p_path) {
525+
return;
526+
}
527+
watch_target_path = p_path;
528+
watching = false;
529+
530+
if (is_inside_tree()) {
531+
_try_watch();
532+
}
533+
}
534+
535+
NodePath ScrollBar::get_watch_target_path() const {
536+
return watch_target_path;
537+
}
538+
539+
bool ScrollBar::is_watching() const {
540+
return watching && has_node(watch_target_path);
541+
}
542+
503543
void ScrollBar::set_custom_step(float p_custom_step) {
504544
custom_step = p_custom_step;
505545
}
@@ -617,12 +657,17 @@ bool ScrollBar::is_smooth_scroll_enabled() const {
617657
}
618658

619659
void ScrollBar::_bind_methods() {
660+
ClassDB::bind_method(D_METHOD("set_watch_target_path", "path"), &ScrollBar::set_watch_target_path);
661+
ClassDB::bind_method(D_METHOD("get_watch_target_path"), &ScrollBar::get_watch_target_path);
662+
ClassDB::bind_method(D_METHOD("is_watching"), &ScrollBar::is_watching);
663+
620664
ClassDB::bind_method(D_METHOD("set_custom_step", "step"), &ScrollBar::set_custom_step);
621665
ClassDB::bind_method(D_METHOD("get_custom_step"), &ScrollBar::get_custom_step);
622666

623667
ADD_SIGNAL(MethodInfo("scrolling"));
624668

625669
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "custom_step", PROPERTY_HINT_RANGE, "-1,4096,suffix:px"), "set_custom_step", "get_custom_step");
670+
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "watch_target_path", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "ScrollContainer"), "set_watch_target_path", "get_watch_target_path");
626671
}
627672

628673
ScrollBar::ScrollBar(Orientation p_orientation) {

scene/gui/scroll_bar.h

+9
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ class ScrollBar : public Range {
4545

4646
static bool focus_by_default;
4747

48+
NodePath watch_target_path;
49+
bool watching = false;
50+
4851
Orientation orientation;
4952
Size2 size;
5053
float custom_step = -1.0;
@@ -89,6 +92,8 @@ class ScrollBar : public Range {
8992
void _drag_node_exit();
9093
void _drag_node_input(const Ref<InputEvent> &p_input);
9194

95+
void _try_watch();
96+
9297
virtual void gui_input(const Ref<InputEvent> &p_event) override;
9398

9499
protected:
@@ -97,6 +102,10 @@ class ScrollBar : public Range {
97102
static void _bind_methods();
98103

99104
public:
105+
void set_watch_target_path(const NodePath p_path);
106+
NodePath get_watch_target_path() const;
107+
bool is_watching() const;
108+
100109
void set_custom_step(float p_custom_step);
101110
float get_custom_step() const;
102111

0 commit comments

Comments
 (0)